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 : }
|