LCOV - code coverage report
Current view: top level - frmts/gtiff - gtiffrasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 234 243 96.3 %
Date: 2024-05-18 15:15:27 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "gtiffrasterband.h"
      31             : #include "gtiffdataset.h"
      32             : 
      33             : #include <algorithm>
      34             : #include <set>
      35             : 
      36             : #include "cpl_vsi_virtual.h"
      37             : #include "tifvsi.h"
      38             : 
      39             : /************************************************************************/
      40             : /*                           GTiffRasterBand()                          */
      41             : /************************************************************************/
      42             : 
      43      686266 : GTiffRasterBand::GTiffRasterBand(GTiffDataset *poDSIn, int nBandIn)
      44      686266 :     : m_poGDS(poDSIn)
      45             : {
      46      686254 :     poDS = poDSIn;
      47      686254 :     nBand = nBandIn;
      48             : 
      49             :     /* -------------------------------------------------------------------- */
      50             :     /*      Get the GDAL data type.                                         */
      51             :     /* -------------------------------------------------------------------- */
      52      686254 :     const uint16_t nBitsPerSample = m_poGDS->m_nBitsPerSample;
      53      686254 :     const uint16_t nSampleFormat = m_poGDS->m_nSampleFormat;
      54             : 
      55      686254 :     eDataType = GDT_Unknown;
      56             : 
      57      686254 :     if (nBitsPerSample <= 8)
      58             :     {
      59      679654 :         if (nSampleFormat == SAMPLEFORMAT_INT)
      60          76 :             eDataType = GDT_Int8;
      61             :         else
      62      679578 :             eDataType = GDT_Byte;
      63             :     }
      64        6600 :     else if (nBitsPerSample <= 16)
      65             :     {
      66        2361 :         if (nSampleFormat == SAMPLEFORMAT_INT)
      67        1163 :             eDataType = GDT_Int16;
      68             :         else
      69        1198 :             eDataType = GDT_UInt16;
      70             :     }
      71        4239 :     else if (nBitsPerSample == 32)
      72             :     {
      73        2845 :         if (nSampleFormat == SAMPLEFORMAT_COMPLEXINT)
      74         461 :             eDataType = GDT_CInt16;
      75        2384 :         else if (nSampleFormat == SAMPLEFORMAT_IEEEFP)
      76        1632 :             eDataType = GDT_Float32;
      77         752 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      78         398 :             eDataType = GDT_Int32;
      79             :         else
      80         354 :             eDataType = GDT_UInt32;
      81             :     }
      82        1394 :     else if (nBitsPerSample == 64)
      83             :     {
      84        1070 :         if (nSampleFormat == SAMPLEFORMAT_IEEEFP)
      85         561 :             eDataType = GDT_Float64;
      86         509 :         else if (nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP)
      87         232 :             eDataType = GDT_CFloat32;
      88         277 :         else if (nSampleFormat == SAMPLEFORMAT_COMPLEXINT)
      89         213 :             eDataType = GDT_CInt32;
      90          64 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      91          32 :             eDataType = GDT_Int64;
      92             :         else
      93          32 :             eDataType = GDT_UInt64;
      94             :     }
      95         324 :     else if (nBitsPerSample == 128)
      96             :     {
      97         252 :         if (nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP)
      98         252 :             eDataType = GDT_CFloat64;
      99             :     }
     100             : 
     101             :     /* -------------------------------------------------------------------- */
     102             :     /*      Try to work out band color interpretation.                      */
     103             :     /* -------------------------------------------------------------------- */
     104      686254 :     bool bLookForExtraSamples = false;
     105             : 
     106      686254 :     if (m_poGDS->m_poColorTable != nullptr && nBand == 1)
     107             :     {
     108         158 :         m_eBandInterp = GCI_PaletteIndex;
     109             :     }
     110     1362690 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB ||
     111      676592 :              (m_poGDS->m_nPhotometric == PHOTOMETRIC_YCBCR &&
     112         873 :               m_poGDS->m_nCompression == COMPRESSION_JPEG &&
     113         834 :               CPLTestBool(CPLGetConfigOption("CONVERT_YCBCR_TO_RGB", "YES"))))
     114             :     {
     115       10326 :         if (nBand == 1)
     116        3126 :             m_eBandInterp = GCI_RedBand;
     117        7200 :         else if (nBand == 2)
     118        3126 :             m_eBandInterp = GCI_GreenBand;
     119        4074 :         else if (nBand == 3)
     120        3126 :             m_eBandInterp = GCI_BlueBand;
     121             :         else
     122         948 :             bLookForExtraSamples = true;
     123             :     }
     124      675770 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_YCBCR)
     125             :     {
     126          39 :         if (nBand == 1)
     127          13 :             m_eBandInterp = GCI_YCbCr_YBand;
     128          26 :         else if (nBand == 2)
     129          13 :             m_eBandInterp = GCI_YCbCr_CbBand;
     130          13 :         else if (nBand == 3)
     131          13 :             m_eBandInterp = GCI_YCbCr_CrBand;
     132             :         else
     133           0 :             bLookForExtraSamples = true;
     134             :     }
     135      675731 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_SEPARATED)
     136             :     {
     137          96 :         if (nBand == 1)
     138          24 :             m_eBandInterp = GCI_CyanBand;
     139          72 :         else if (nBand == 2)
     140          24 :             m_eBandInterp = GCI_MagentaBand;
     141          48 :         else if (nBand == 3)
     142          24 :             m_eBandInterp = GCI_YellowBand;
     143          24 :         else if (nBand == 4)
     144          24 :             m_eBandInterp = GCI_BlackBand;
     145             :         else
     146           0 :             bLookForExtraSamples = true;
     147             :     }
     148      675635 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK && nBand == 1)
     149             :     {
     150       17798 :         m_eBandInterp = GCI_GrayIndex;
     151             :     }
     152             :     else
     153             :     {
     154      657837 :         bLookForExtraSamples = true;
     155             :     }
     156             : 
     157      686254 :     if (bLookForExtraSamples)
     158             :     {
     159      658759 :         uint16_t *v = nullptr;
     160      658759 :         uint16_t count = 0;
     161             : 
     162      658759 :         if (TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v))
     163             :         {
     164      592916 :             const int nBaseSamples = m_poGDS->m_nSamplesPerPixel - count;
     165      592916 :             const int nExpectedBaseSamples =
     166      593868 :                 (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK)   ? 1
     167        1904 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISWHITE) ? 1
     168         958 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB)        ? 3
     169          12 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_YCBCR)      ? 3
     170           6 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_SEPARATED)  ? 4
     171             :                                                                       : 0;
     172             : 
     173      592916 :             if (nExpectedBaseSamples > 0 && nBand == nExpectedBaseSamples + 1 &&
     174             :                 nBaseSamples != nExpectedBaseSamples)
     175             :             {
     176           1 :                 ReportError(
     177             :                     CE_Warning, CPLE_AppDefined,
     178             :                     "Wrong number of ExtraSamples : %d. %d were expected",
     179           1 :                     count, m_poGDS->m_nSamplesPerPixel - nExpectedBaseSamples);
     180             :             }
     181             : 
     182      592916 :             if (nBand > nBaseSamples && nBand - nBaseSamples - 1 < count &&
     183      592911 :                 (v[nBand - nBaseSamples - 1] == EXTRASAMPLE_ASSOCALPHA ||
     184      592902 :                  v[nBand - nBaseSamples - 1] == EXTRASAMPLE_UNASSALPHA))
     185        1009 :                 m_eBandInterp = GCI_AlphaBand;
     186             :             else
     187      591907 :                 m_eBandInterp = GCI_Undefined;
     188             :         }
     189             :         else
     190             :         {
     191       65843 :             m_eBandInterp = GCI_Undefined;
     192             :         }
     193             :     }
     194             : 
     195             :     /* -------------------------------------------------------------------- */
     196             :     /*      Establish block size for strip or tiles.                        */
     197             :     /* -------------------------------------------------------------------- */
     198      686254 :     nBlockXSize = m_poGDS->m_nBlockXSize;
     199      686254 :     nBlockYSize = m_poGDS->m_nBlockYSize;
     200      686254 :     nRasterXSize = m_poGDS->nRasterXSize;
     201      686254 :     nRasterYSize = m_poGDS->nRasterYSize;
     202      686254 :     nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
     203      686254 :     nBlocksPerColumn = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
     204      686254 : }
     205             : 
     206             : /************************************************************************/
     207             : /*                          ~GTiffRasterBand()                          */
     208             : /************************************************************************/
     209             : 
     210     1240535 : GTiffRasterBand::~GTiffRasterBand()
     211             : {
     212             :     // So that any future DropReferenceVirtualMem() will not try to access the
     213             :     // raster band object, but this would not conform to the advertised
     214             :     // contract.
     215      686272 :     if (!m_aSetPSelf.empty())
     216             :     {
     217           0 :         ReportError(CE_Warning, CPLE_AppDefined,
     218             :                     "Virtual memory objects still exist at GTiffRasterBand "
     219             :                     "destruction");
     220           0 :         std::set<GTiffRasterBand **>::iterator oIter = m_aSetPSelf.begin();
     221           0 :         for (; oIter != m_aSetPSelf.end(); ++oIter)
     222           0 :             *(*oIter) = nullptr;
     223             :     }
     224     1240534 : }
     225             : 
     226             : /************************************************************************/
     227             : /*                            IRasterIO()                               */
     228             : /************************************************************************/
     229             : 
     230     2719670 : CPLErr GTiffRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     231             :                                   int nXSize, int nYSize, void *pData,
     232             :                                   int nBufXSize, int nBufYSize,
     233             :                                   GDALDataType eBufType, GSpacing nPixelSpace,
     234             :                                   GSpacing nLineSpace,
     235             :                                   GDALRasterIOExtraArg *psExtraArg)
     236             : {
     237             : #if DEBUG_VERBOSE
     238             :     CPLDebug("GTiff", "RasterIO(%d, %d, %d, %d, %d, %d)", nXOff, nYOff, nXSize,
     239             :              nYSize, nBufXSize, nBufYSize);
     240             : #endif
     241             : 
     242             :     // Try to pass the request to the most appropriate overview dataset.
     243     2719670 :     if (nBufXSize < nXSize && nBufYSize < nYSize)
     244             :     {
     245      161921 :         int bTried = FALSE;
     246      161921 :         if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     247      161567 :             ++m_poGDS->m_nJPEGOverviewVisibilityCounter;
     248      161921 :         const CPLErr eErr = TryOverviewRasterIO(
     249             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     250             :             eBufType, nPixelSpace, nLineSpace, psExtraArg, &bTried);
     251      161921 :         if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     252      161567 :             --m_poGDS->m_nJPEGOverviewVisibilityCounter;
     253      161921 :         if (bTried)
     254          37 :             return eErr;
     255             :     }
     256             : 
     257     2719630 :     if (m_poGDS->m_eVirtualMemIOUsage != GTiffDataset::VirtualMemIOEnum::NO)
     258             :     {
     259         452 :         const int nErr = m_poGDS->VirtualMemIO(
     260             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     261             :             eBufType, 1, &nBand, nPixelSpace, nLineSpace, 0, psExtraArg);
     262         452 :         if (nErr >= 0)
     263         363 :             return static_cast<CPLErr>(nErr);
     264             :     }
     265     2719270 :     if (m_poGDS->m_bDirectIO)
     266             :     {
     267             :         int nErr =
     268        1247 :             DirectIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
     269             :                      nBufYSize, eBufType, nPixelSpace, nLineSpace, psExtraArg);
     270        1247 :         if (nErr >= 0)
     271         985 :             return static_cast<CPLErr>(nErr);
     272             :     }
     273             : 
     274     2718290 :     bool bCanUseMultiThreadedRead = false;
     275     2718260 :     if (m_poGDS->m_nDisableMultiThreadedRead == 0 && eRWFlag == GF_Read &&
     276     2473620 :         m_poGDS->m_poThreadPool != nullptr && nXSize == nBufXSize &&
     277     5436540 :         nYSize == nBufYSize && m_poGDS->IsMultiThreadedReadCompatible())
     278             :     {
     279         101 :         const int nBlockX1 = nXOff / nBlockXSize;
     280         101 :         const int nBlockY1 = nYOff / nBlockYSize;
     281         101 :         const int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
     282         101 :         const int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
     283         101 :         const int nXBlocks = nBlockX2 - nBlockX1 + 1;
     284         101 :         const int nYBlocks = nBlockY2 - nBlockY1 + 1;
     285         101 :         if (nXBlocks > 1 || nYBlocks > 1)
     286             :         {
     287          98 :             bCanUseMultiThreadedRead = true;
     288             :         }
     289             :     }
     290             : 
     291             :     // Cleanup data cached by below CacheMultiRange() call.
     292             :     struct BufferedDataFreer
     293             :     {
     294             :         void *m_pBufferedData = nullptr;
     295             :         TIFF *m_hTIFF = nullptr;
     296             : 
     297         123 :         void Init(void *pBufferedData, TIFF *hTIFF)
     298             :         {
     299         123 :             m_pBufferedData = pBufferedData;
     300         123 :             m_hTIFF = hTIFF;
     301         123 :         }
     302             : 
     303     2718390 :         ~BufferedDataFreer()
     304     2718390 :         {
     305     2718390 :             if (m_pBufferedData)
     306             :             {
     307          35 :                 VSIFree(m_pBufferedData);
     308          35 :                 VSI_TIFFSetCachedRanges(TIFFClientdata(m_hTIFF), 0, nullptr,
     309             :                                         nullptr, nullptr);
     310             :             }
     311     2718390 :         }
     312             :     };
     313             : 
     314             :     // bufferedDataFreer must be left in this scope !
     315     2718380 :     BufferedDataFreer bufferedDataFreer;
     316             : 
     317     4926360 :     if (m_poGDS->eAccess == GA_ReadOnly && eRWFlag == GF_Read &&
     318     2208080 :         m_poGDS->HasOptimizedReadMultiRange())
     319             :     {
     320         127 :         if (bCanUseMultiThreadedRead &&
     321           2 :             VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF))->HasPRead())
     322             :         {
     323             :             // use the multi-threaded implementation rather than the multi-range
     324             :             // one
     325             :         }
     326             :         else
     327             :         {
     328         123 :             bCanUseMultiThreadedRead = false;
     329         123 :             GTiffRasterBand *poBandForCache = this;
     330         123 :             if (!m_poGDS->m_bStreamingIn && m_poGDS->m_bBlockOrderRowMajor &&
     331         106 :                 m_poGDS->m_bLeaderSizeAsUInt4 &&
     332         106 :                 m_poGDS->m_bMaskInterleavedWithImagery &&
     333         102 :                 m_poGDS->m_poImageryDS)
     334             :             {
     335          63 :                 poBandForCache = cpl::down_cast<GTiffRasterBand *>(
     336          63 :                     m_poGDS->m_poImageryDS->GetRasterBand(1));
     337             :             }
     338         123 :             bufferedDataFreer.Init(poBandForCache->CacheMultiRange(
     339             :                                        nXOff, nYOff, nXSize, nYSize, nBufXSize,
     340             :                                        nBufYSize, psExtraArg),
     341         123 :                                    poBandForCache->m_poGDS->m_hTIFF);
     342             :         }
     343             :     }
     344             : 
     345     2718010 :     if (eRWFlag == GF_Read && nXSize == nBufXSize && nYSize == nBufYSize)
     346             :     {
     347     2278260 :         const int nBlockX1 = nXOff / nBlockXSize;
     348     2278260 :         const int nBlockY1 = nYOff / nBlockYSize;
     349     2278260 :         const int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
     350     2278260 :         const int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
     351     2278260 :         const int nXBlocks = nBlockX2 - nBlockX1 + 1;
     352     2278260 :         const int nYBlocks = nBlockY2 - nBlockY1 + 1;
     353             : 
     354     2278260 :         if (bCanUseMultiThreadedRead)
     355             :         {
     356         196 :             return m_poGDS->MultiThreadedRead(nXOff, nYOff, nXSize, nYSize,
     357          98 :                                               pData, eBufType, 1, &nBand,
     358          98 :                                               nPixelSpace, nLineSpace, 0);
     359             :         }
     360     2278160 :         else if (m_poGDS->nBands != 1 &&
     361      112717 :                  m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     362             :         {
     363             :             const GIntBig nRequiredMem =
     364       65932 :                 static_cast<GIntBig>(m_poGDS->nBands) * nXBlocks * nYBlocks *
     365       65932 :                 nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eDataType);
     366       65932 :             if (nRequiredMem > GDALGetCacheMax64())
     367             :             {
     368          12 :                 if (!m_poGDS->m_bHasWarnedDisableAggressiveBandCaching)
     369             :                 {
     370          10 :                     CPLDebug("GTiff",
     371             :                              "Disable aggressive band caching. "
     372             :                              "Cache not big enough. "
     373             :                              "At least " CPL_FRMT_GIB " bytes necessary",
     374             :                              nRequiredMem);
     375          10 :                     m_poGDS->m_bHasWarnedDisableAggressiveBandCaching = true;
     376             :                 }
     377          12 :                 m_poGDS->m_bLoadingOtherBands = true;
     378             :             }
     379     2278160 :         }
     380             :     }
     381             : 
     382             :     // Write optimization when writing whole blocks, by-passing the block cache.
     383             :     // We require the block cache to be non instantiated to simplify things
     384             :     // (otherwise we might need to evict corresponding existing blocks from the
     385             :     // block cache).
     386      684315 :     else if (eRWFlag == GF_Write &&
     387             :              // Could be extended to "odd bit" case, but more work
     388      244732 :              m_poGDS->m_nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
     389       92470 :              nXSize == nBufXSize && nYSize == nBufYSize && !HasBlockCache() &&
     390       43560 :              !m_poGDS->m_bLoadedBlockDirty &&
     391       43591 :              (m_poGDS->nBands == 1 ||
     392        1606 :               m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE) &&
     393       42687 :              (nXOff % nBlockXSize) == 0 && (nYOff % nBlockYSize) == 0 &&
     394      726787 :              (nXOff + nXSize == nRasterXSize || (nXSize % nBlockXSize) == 0) &&
     395       42349 :              (nYOff + nYSize == nRasterYSize || (nYSize % nBlockYSize) == 0))
     396             :     {
     397       42127 :         m_poGDS->Crystalize();
     398             : 
     399       42549 :         if (m_poGDS->m_bDebugDontWriteBlocks)
     400           0 :             return CE_None;
     401             : 
     402       42549 :         const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
     403       42356 :         if (nXSize == nBlockXSize && nYSize == nBlockYSize &&
     404       40543 :             eBufType == eDataType && nPixelSpace == nDTSize &&
     405       40584 :             nLineSpace == nPixelSpace * nBlockXSize)
     406             :         {
     407             :             // If writing one single block with the right data type and layout,
     408             :             // we don't need a temporary buffer
     409             :             const int nBlockId =
     410       40851 :                 ComputeBlockId(nXOff / nBlockXSize, nYOff / nBlockYSize);
     411       40771 :             return m_poGDS->WriteEncodedTileOrStrip(
     412       41191 :                 nBlockId, pData, /* bPreserveDataBuffer= */ true);
     413             :         }
     414             : 
     415             :         // Make sure m_poGDS->m_pabyBlockBuf is allocated.
     416             :         // We could actually use any temporary buffer
     417        1505 :         if (m_poGDS->LoadBlockBuf(/* nBlockId = */ -1,
     418        1385 :                                   /* bReadFromDisk = */ false) != CE_None)
     419             :         {
     420           0 :             return CE_Failure;
     421             :         }
     422             : 
     423             :         // Iterate over all blocks defined by
     424             :         // [nXOff, nXOff+nXSize[ * [nYOff, nYOff+nYSize[
     425             :         // and write their content as a nBlockXSize x nBlockYSize strile
     426             :         // in a temporary buffer, before calling WriteEncodedTileOrStrip()
     427             :         // on it
     428        1385 :         const int nYBlockStart = nYOff / nBlockYSize;
     429        1385 :         const int nYBlockEnd = 1 + (nYOff + nYSize - 1) / nBlockYSize;
     430        1385 :         const int nXBlockStart = nXOff / nBlockXSize;
     431        1385 :         const int nXBlockEnd = 1 + (nXOff + nXSize - 1) / nBlockXSize;
     432       25407 :         for (int nYBlock = nYBlockStart; nYBlock < nYBlockEnd; ++nYBlock)
     433             :         {
     434             :             const int nValidY =
     435       24022 :                 std::min(nBlockYSize, nRasterYSize - nYBlock * nBlockYSize);
     436       61785 :             for (int nXBlock = nXBlockStart; nXBlock < nXBlockEnd; ++nXBlock)
     437             :             {
     438             :                 const int nValidX =
     439       37763 :                     std::min(nBlockXSize, nRasterXSize - nXBlock * nBlockXSize);
     440       37758 :                 if (nValidY < nBlockYSize || nValidX < nBlockXSize)
     441             :                 {
     442             :                     // Make sure padding bytes at the right/bottom of the
     443             :                     // tile are initialized to zero.
     444        2175 :                     memset(m_poGDS->m_pabyBlockBuf, 0,
     445        2175 :                            static_cast<size_t>(nBlockXSize) * nBlockYSize *
     446        2175 :                                nDTSize);
     447             :                 }
     448       37758 :                 const GByte *pabySrcData =
     449             :                     static_cast<const GByte *>(pData) +
     450       37758 :                     static_cast<size_t>(nYBlock - nYBlockStart) * nBlockYSize *
     451       37758 :                         nLineSpace +
     452       37758 :                     static_cast<size_t>(nXBlock - nXBlockStart) * nBlockXSize *
     453       37758 :                         nPixelSpace;
     454     1237330 :                 for (int iY = 0; iY < nValidY; ++iY)
     455             :                 {
     456     1199570 :                     GDALCopyWords64(
     457     1199570 :                         pabySrcData + static_cast<size_t>(iY) * nLineSpace,
     458             :                         eBufType, static_cast<int>(nPixelSpace),
     459     1199570 :                         m_poGDS->m_pabyBlockBuf +
     460     1199570 :                             static_cast<size_t>(iY) * nBlockXSize * nDTSize,
     461             :                         eDataType, nDTSize, nValidX);
     462             :                 }
     463       37763 :                 const int nBlockId = ComputeBlockId(nXBlock, nYBlock);
     464       75526 :                 if (m_poGDS->WriteEncodedTileOrStrip(
     465       37763 :                         nBlockId, m_poGDS->m_pabyBlockBuf,
     466       37763 :                         /* bPreserveDataBuffer= */ false) != CE_None)
     467             :                 {
     468           0 :                     return CE_Failure;
     469             :                 }
     470             :             }
     471             :         }
     472        1385 :         return CE_None;
     473             :     }
     474             : 
     475     2675740 :     if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     476     2673290 :         ++m_poGDS->m_nJPEGOverviewVisibilityCounter;
     477     2675740 :     const CPLErr eErr = GDALPamRasterBand::IRasterIO(
     478             :         eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     479             :         eBufType, nPixelSpace, nLineSpace, psExtraArg);
     480     2675700 :     if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     481     2673290 :         --m_poGDS->m_nJPEGOverviewVisibilityCounter;
     482             : 
     483     2675700 :     m_poGDS->m_bLoadingOtherBands = false;
     484             : 
     485     2675700 :     return eErr;
     486             : }
     487             : 
     488             : /************************************************************************/
     489             : /*                        ComputeBlockId()                              */
     490             : /************************************************************************/
     491             : 
     492             : /** Computes the TIFF block identifier from the tile coordinate, band
     493             :  * number and planar configuration.
     494             :  */
     495     3109510 : int GTiffRasterBand::ComputeBlockId(int nBlockXOff, int nBlockYOff) const
     496             : {
     497     3109510 :     const int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
     498     3109510 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     499             :     {
     500      402523 :         return nBlockId + (nBand - 1) * m_poGDS->m_nBlocksPerBand;
     501             :     }
     502     2706990 :     return nBlockId;
     503             : }

Generated by: LCOV version 1.14