Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GeoTIFF Driver
4 : * Purpose: Read/get operations on 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 : #include "gtiffjpegoverviewds.h"
17 :
18 : #include <algorithm>
19 : #include <cassert>
20 : #include <limits>
21 : #include <map>
22 : #include <set>
23 : #include <utility>
24 :
25 : #include "cpl_vsi_virtual.h"
26 : #include "fetchbufferdirectio.h"
27 : #include "gtiff.h"
28 : #include "tifvsi.h"
29 :
30 : /************************************************************************/
31 : /* GetDefaultRAT() */
32 : /************************************************************************/
33 :
34 3410 : GDALRasterAttributeTable *GTiffRasterBand::GetDefaultRAT()
35 :
36 : {
37 3410 : if (m_poRAT)
38 2 : return m_poRAT.get();
39 :
40 3408 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
41 3408 : auto poRAT = GDALPamRasterBand::GetDefaultRAT();
42 3408 : if (poRAT)
43 7 : return poRAT;
44 :
45 3401 : if (!GDALCanFileAcceptSidecarFile(m_poGDS->m_pszFilename))
46 0 : return nullptr;
47 : const std::string osVATDBF =
48 10203 : std::string(m_poGDS->m_pszFilename) + ".vat.dbf";
49 3401 : CSLConstList papszSiblingFiles = m_poGDS->GetSiblingFiles();
50 6768 : if (papszSiblingFiles &&
51 : // cppcheck-suppress knownConditionTrueFalse
52 3367 : GDALCanReliablyUseSiblingFileList(osVATDBF.c_str()))
53 : {
54 : int iSibling =
55 3367 : CSLFindString(papszSiblingFiles, CPLGetFilename(osVATDBF.c_str()));
56 3367 : if (iSibling >= 0)
57 : {
58 2 : CPLString osFilename = m_poGDS->m_pszFilename;
59 4 : osFilename.resize(strlen(m_poGDS->m_pszFilename) -
60 2 : strlen(CPLGetFilename(m_poGDS->m_pszFilename)));
61 2 : osFilename += papszSiblingFiles[iSibling];
62 2 : m_poRAT = GDALLoadVATDBF(osFilename.c_str());
63 : }
64 3367 : return m_poRAT.get();
65 : }
66 : VSIStatBufL sStatBuf;
67 34 : if (VSIStatL(osVATDBF.c_str(), &sStatBuf) == 0)
68 1 : m_poRAT = GDALLoadVATDBF(osVATDBF.c_str());
69 34 : return m_poRAT.get();
70 : }
71 :
72 : /************************************************************************/
73 : /* GetHistogram() */
74 : /************************************************************************/
75 :
76 20 : CPLErr GTiffRasterBand::GetHistogram(double dfMin, double dfMax, int nBuckets,
77 : GUIntBig *panHistogram,
78 : int bIncludeOutOfRange, int bApproxOK,
79 : GDALProgressFunc pfnProgress,
80 : void *pProgressData)
81 : {
82 20 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
83 20 : return GDALPamRasterBand::GetHistogram(dfMin, dfMax, nBuckets, panHistogram,
84 : bIncludeOutOfRange, bApproxOK,
85 20 : pfnProgress, pProgressData);
86 : }
87 :
88 : /************************************************************************/
89 : /* GetDefaultHistogram() */
90 : /************************************************************************/
91 :
92 21 : CPLErr GTiffRasterBand::GetDefaultHistogram(
93 : double *pdfMin, double *pdfMax, int *pnBuckets, GUIntBig **ppanHistogram,
94 : int bForce, GDALProgressFunc pfnProgress, void *pProgressData)
95 : {
96 21 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
97 21 : return GDALPamRasterBand::GetDefaultHistogram(pdfMin, pdfMax, pnBuckets,
98 : ppanHistogram, bForce,
99 21 : pfnProgress, pProgressData);
100 : }
101 :
102 : /************************************************************************/
103 : /* DirectIO() */
104 : /************************************************************************/
105 :
106 : // Reads directly bytes from the file using ReadMultiRange(), and by-pass
107 : // block reading. Restricted to simple TIFF configurations
108 : // (uncompressed data, standard data types). Particularly useful to extract
109 : // sub-windows of data on a large /vsicurl dataset).
110 : // Returns -1 if DirectIO() can't be supported on that file.
111 :
112 2098 : int GTiffRasterBand::DirectIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
113 : int nXSize, int nYSize, void *pData,
114 : int nBufXSize, int nBufYSize,
115 : GDALDataType eBufType, GSpacing nPixelSpace,
116 : GSpacing nLineSpace,
117 : GDALRasterIOExtraArg *psExtraArg)
118 : {
119 2098 : const int nDTSizeBits = GDALGetDataTypeSizeBits(eDataType);
120 4196 : if (!(eRWFlag == GF_Read && m_poGDS->m_nCompression == COMPRESSION_NONE &&
121 2098 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK ||
122 795 : m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB ||
123 0 : m_poGDS->m_nPhotometric == PHOTOMETRIC_PALETTE) &&
124 2098 : IsBaseGTiffClass()))
125 : {
126 0 : return -1;
127 : }
128 2098 : m_poGDS->Crystalize();
129 :
130 : // Only know how to deal with nearest neighbour in this optimized routine.
131 2098 : if ((nXSize != nBufXSize || nYSize != nBufYSize) && psExtraArg != nullptr &&
132 447 : psExtraArg->eResampleAlg != GRIORA_NearestNeighbour)
133 : {
134 66 : return -1;
135 : }
136 :
137 : #if DEBUG_VERBOSE
138 : CPLDebug("GTiff", "DirectIO(%d,%d,%d,%d -> %dx%d)", nXOff, nYOff, nXSize,
139 : nYSize, nBufXSize, nBufYSize);
140 : #endif
141 :
142 : // Make sure that TIFFTAG_STRIPOFFSETS is up-to-date.
143 2032 : if (m_poGDS->GetAccess() == GA_Update)
144 : {
145 0 : m_poGDS->FlushCache(false);
146 0 : VSI_TIFFFlushBufferedWrite(TIFFClientdata(m_poGDS->m_hTIFF));
147 : }
148 :
149 2032 : if (TIFFIsTiled(m_poGDS->m_hTIFF))
150 : {
151 504 : const int nDTSize = nDTSizeBits / 8;
152 504 : const size_t nTempBufferForCommonDirectIOSize = static_cast<size_t>(
153 1008 : static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize * nDTSize *
154 504 : (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG ? m_poGDS->nBands
155 : : 1));
156 504 : if (m_poGDS->m_pTempBufferForCommonDirectIO == nullptr)
157 : {
158 28 : m_poGDS->m_pTempBufferForCommonDirectIO = static_cast<GByte *>(
159 14 : VSI_MALLOC_VERBOSE(nTempBufferForCommonDirectIOSize));
160 14 : if (m_poGDS->m_pTempBufferForCommonDirectIO == nullptr)
161 0 : return CE_Failure;
162 : }
163 :
164 504 : VSILFILE *fp = VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF));
165 : FetchBufferDirectIO oFetcher(fp,
166 504 : m_poGDS->m_pTempBufferForCommonDirectIO,
167 504 : nTempBufferForCommonDirectIOSize);
168 :
169 1008 : return m_poGDS->CommonDirectIOClassic(
170 : oFetcher, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
171 504 : eBufType, 1, &nBand, nPixelSpace, nLineSpace, 0);
172 : }
173 :
174 : // Get strip offsets.
175 1528 : toff_t *panTIFFOffsets = nullptr;
176 1528 : if (!TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_STRIPOFFSETS,
177 3056 : &panTIFFOffsets) ||
178 1528 : panTIFFOffsets == nullptr)
179 : {
180 0 : return CE_Failure;
181 : }
182 :
183 : // Sub-sampling or over-sampling can only be done at last stage.
184 1528 : int nReqXSize = nXSize;
185 : // Can do sub-sampling at the extraction stage.
186 1528 : const int nReqYSize = std::min(nBufYSize, nYSize);
187 : // TODO(schwehr): Make ppData be GByte**.
188 : void **ppData =
189 1528 : static_cast<void **>(VSI_MALLOC_VERBOSE(nReqYSize * sizeof(void *)));
190 : vsi_l_offset *panOffsets = static_cast<vsi_l_offset *>(
191 1528 : VSI_MALLOC_VERBOSE(nReqYSize * sizeof(vsi_l_offset)));
192 : size_t *panSizes =
193 1528 : static_cast<size_t *>(VSI_MALLOC_VERBOSE(nReqYSize * sizeof(size_t)));
194 1528 : const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
195 1528 : void *pTmpBuffer = nullptr;
196 1528 : int eErr = CE_None;
197 1528 : int nContigBands =
198 1528 : m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG ? m_poGDS->nBands : 1;
199 1528 : int nSrcPixelSize = nDTSize * nContigBands;
200 :
201 1528 : if (ppData == nullptr || panOffsets == nullptr || panSizes == nullptr)
202 0 : eErr = CE_Failure;
203 1295 : else if (nXSize != nBufXSize || nYSize != nBufYSize ||
204 1295 : eBufType != eDataType ||
205 2823 : nPixelSpace != GDALGetDataTypeSizeBytes(eBufType) ||
206 : nContigBands > 1)
207 : {
208 : // We need a temporary buffer for over-sampling/sub-sampling
209 : // and/or data type conversion.
210 1388 : pTmpBuffer = VSI_MALLOC3_VERBOSE(nReqXSize, nReqYSize, nSrcPixelSize);
211 1388 : if (pTmpBuffer == nullptr)
212 0 : eErr = CE_Failure;
213 : }
214 :
215 : // Prepare data extraction.
216 1528 : const double dfSrcYInc = nYSize / static_cast<double>(nBufYSize);
217 :
218 41509 : for (int iLine = 0; eErr == CE_None && iLine < nReqYSize; ++iLine)
219 : {
220 39981 : if (pTmpBuffer == nullptr)
221 10980 : ppData[iLine] = static_cast<GByte *>(pData) + iLine * nLineSpace;
222 : else
223 29001 : ppData[iLine] =
224 29001 : static_cast<GByte *>(pTmpBuffer) +
225 29001 : static_cast<size_t>(iLine) * nReqXSize * nSrcPixelSize;
226 39981 : int nSrcLine = 0;
227 39981 : if (nBufYSize < nYSize) // Sub-sampling in y.
228 2440 : nSrcLine = nYOff + static_cast<int>((iLine + 0.5) * dfSrcYInc);
229 : else
230 37541 : nSrcLine = nYOff + iLine;
231 :
232 39981 : const int nBlockXOff = 0;
233 39981 : const int nBlockYOff = nSrcLine / nBlockYSize;
234 39981 : const int nYOffsetInBlock = nSrcLine % nBlockYSize;
235 39981 : const int nBlockId = ComputeBlockId(nBlockXOff, nBlockYOff);
236 :
237 39981 : panOffsets[iLine] = panTIFFOffsets[nBlockId];
238 39981 : if (panOffsets[iLine] == 0) // We don't support sparse files.
239 1047 : eErr = -1;
240 :
241 39981 : panOffsets[iLine] +=
242 39981 : (nXOff + static_cast<vsi_l_offset>(nYOffsetInBlock) * nBlockXSize) *
243 39981 : nSrcPixelSize;
244 39981 : panSizes[iLine] = static_cast<size_t>(nReqXSize) * nSrcPixelSize;
245 : }
246 :
247 : // Extract data from the file.
248 1528 : if (eErr == CE_None)
249 : {
250 481 : VSILFILE *fp = VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF));
251 : const int nRet =
252 481 : VSIFReadMultiRangeL(nReqYSize, ppData, panOffsets, panSizes, fp);
253 481 : if (nRet != 0)
254 12 : eErr = CE_Failure;
255 : }
256 :
257 : // Byte-swap if necessary.
258 1528 : if (eErr == CE_None && TIFFIsByteSwapped(m_poGDS->m_hTIFF))
259 : {
260 4144 : for (int iLine = 0; iLine < nReqYSize; ++iLine)
261 : {
262 4094 : if (GDALDataTypeIsComplex(eDataType))
263 2396 : GDALSwapWords(ppData[iLine], nDTSize / 2,
264 2396 : 2 * nReqXSize * nContigBands, nDTSize / 2);
265 : else
266 1698 : GDALSwapWords(ppData[iLine], nDTSize, nReqXSize * nContigBands,
267 : nDTSize);
268 : }
269 : }
270 :
271 : // Over-sampling/sub-sampling and/or data type conversion.
272 1528 : const double dfSrcXInc = nXSize / static_cast<double>(nBufXSize);
273 1528 : if (eErr == CE_None && pTmpBuffer != nullptr)
274 : {
275 364 : const bool bOneByteCopy =
276 656 : (eDataType == eBufType &&
277 292 : (eDataType == GDT_Byte || eDataType == GDT_Int8));
278 96459 : for (int iY = 0; iY < nBufYSize; ++iY)
279 : {
280 192190 : const int iSrcY = nBufYSize <= nYSize
281 96095 : ? iY
282 73872 : : static_cast<int>((iY + 0.5) * dfSrcYInc);
283 :
284 192190 : GByte *pabySrcData = static_cast<GByte *>(ppData[iSrcY]) +
285 96095 : (nContigBands > 1 ? (nBand - 1) : 0) * nDTSize;
286 96095 : GByte *pabyDstData = static_cast<GByte *>(pData) + iY * nLineSpace;
287 96095 : if (nBufXSize == nXSize)
288 : {
289 19798 : GDALCopyWords(pabySrcData, eDataType, nSrcPixelSize,
290 : pabyDstData, eBufType,
291 : static_cast<int>(nPixelSpace), nBufXSize);
292 : }
293 : else
294 : {
295 76297 : if (bOneByteCopy)
296 : {
297 25435 : double dfSrcX = 0.5 * dfSrcXInc;
298 2147110 : for (int iX = 0; iX < nBufXSize; ++iX, dfSrcX += dfSrcXInc)
299 : {
300 2121670 : const int iSrcX = static_cast<int>(dfSrcX);
301 2121670 : pabyDstData[iX * nPixelSpace] =
302 2121670 : pabySrcData[iSrcX * nSrcPixelSize];
303 : }
304 : }
305 : else
306 : {
307 50862 : double dfSrcX = 0.5 * dfSrcXInc;
308 4293180 : for (int iX = 0; iX < nBufXSize; ++iX, dfSrcX += dfSrcXInc)
309 : {
310 4242320 : const int iSrcX = static_cast<int>(dfSrcX);
311 4242320 : GDALCopyWords(
312 4242320 : pabySrcData + iSrcX * nSrcPixelSize, eDataType, 0,
313 4242320 : pabyDstData + iX * nPixelSpace, eBufType, 0, 1);
314 : }
315 : }
316 : }
317 : }
318 : }
319 :
320 : // Cleanup.
321 1528 : CPLFree(pTmpBuffer);
322 1528 : CPLFree(ppData);
323 1528 : CPLFree(panOffsets);
324 1528 : CPLFree(panSizes);
325 :
326 1528 : return eErr;
327 : }
328 :
329 : /************************************************************************/
330 : /* GetVirtualMemAuto() */
331 : /************************************************************************/
332 :
333 17 : CPLVirtualMem *GTiffRasterBand::GetVirtualMemAuto(GDALRWFlag eRWFlag,
334 : int *pnPixelSpace,
335 : GIntBig *pnLineSpace,
336 : char **papszOptions)
337 : {
338 17 : const char *pszImpl = CSLFetchNameValueDef(
339 : papszOptions, "USE_DEFAULT_IMPLEMENTATION", "AUTO");
340 17 : if (EQUAL(pszImpl, "YES") || EQUAL(pszImpl, "ON") || EQUAL(pszImpl, "1") ||
341 16 : EQUAL(pszImpl, "TRUE"))
342 : {
343 1 : return GDALRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
344 1 : pnLineSpace, papszOptions);
345 : }
346 :
347 16 : CPLVirtualMem *psRet = GetVirtualMemAutoInternal(eRWFlag, pnPixelSpace,
348 : pnLineSpace, papszOptions);
349 16 : if (psRet != nullptr)
350 : {
351 14 : CPLDebug("GTiff", "GetVirtualMemAuto(): Using memory file mapping");
352 14 : return psRet;
353 : }
354 :
355 2 : if (EQUAL(pszImpl, "NO") || EQUAL(pszImpl, "OFF") || EQUAL(pszImpl, "0") ||
356 1 : EQUAL(pszImpl, "FALSE"))
357 : {
358 1 : return nullptr;
359 : }
360 :
361 1 : CPLDebug("GTiff", "GetVirtualMemAuto(): Defaulting to base implementation");
362 1 : return GDALRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace, pnLineSpace,
363 1 : papszOptions);
364 : }
365 :
366 : /************************************************************************/
367 : /* DropReferenceVirtualMem() */
368 : /************************************************************************/
369 :
370 8 : void GTiffRasterBand::DropReferenceVirtualMem(void *pUserData)
371 : {
372 : // This function may also be called when the dataset and rasterband
373 : // objects have been destroyed.
374 : // If they are still alive, it updates the reference counter of the
375 : // base mapping to invalidate the pointer to it if needed.
376 :
377 8 : GTiffRasterBand **ppoSelf = static_cast<GTiffRasterBand **>(pUserData);
378 8 : GTiffRasterBand *poSelf = *ppoSelf;
379 :
380 8 : if (poSelf != nullptr)
381 : {
382 8 : if (--(poSelf->m_poGDS->m_nRefBaseMapping) == 0)
383 : {
384 4 : poSelf->m_poGDS->m_pBaseMapping = nullptr;
385 : }
386 8 : poSelf->m_aSetPSelf.erase(ppoSelf);
387 : }
388 8 : CPLFree(pUserData);
389 8 : }
390 :
391 : /************************************************************************/
392 : /* GetVirtualMemAutoInternal() */
393 : /************************************************************************/
394 :
395 20 : CPLVirtualMem *GTiffRasterBand::GetVirtualMemAutoInternal(GDALRWFlag eRWFlag,
396 : int *pnPixelSpace,
397 : GIntBig *pnLineSpace,
398 : char **papszOptions)
399 : {
400 20 : int nLineSize = nBlockXSize * GDALGetDataTypeSizeBytes(eDataType);
401 20 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
402 14 : nLineSize *= m_poGDS->nBands;
403 :
404 20 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
405 : {
406 : // In case of a pixel interleaved file, we save virtual memory space
407 : // by reusing a base mapping that embraces the whole imagery.
408 14 : if (m_poGDS->m_pBaseMapping != nullptr)
409 : {
410 : // Offset between the base mapping and the requested mapping.
411 8 : vsi_l_offset nOffset = static_cast<vsi_l_offset>(nBand - 1) *
412 8 : GDALGetDataTypeSizeBytes(eDataType);
413 :
414 : GTiffRasterBand **ppoSelf = static_cast<GTiffRasterBand **>(
415 8 : CPLCalloc(1, sizeof(GTiffRasterBand *)));
416 8 : *ppoSelf = this;
417 :
418 24 : CPLVirtualMem *pVMem = CPLVirtualMemDerivedNew(
419 8 : m_poGDS->m_pBaseMapping, nOffset,
420 8 : CPLVirtualMemGetSize(m_poGDS->m_pBaseMapping) - nOffset,
421 : GTiffRasterBand::DropReferenceVirtualMem, ppoSelf);
422 8 : if (pVMem == nullptr)
423 : {
424 0 : CPLFree(ppoSelf);
425 0 : return nullptr;
426 : }
427 :
428 : // Mechanism used so that the memory mapping object can be
429 : // destroyed after the raster band.
430 8 : m_aSetPSelf.insert(ppoSelf);
431 8 : ++m_poGDS->m_nRefBaseMapping;
432 8 : *pnPixelSpace = GDALGetDataTypeSizeBytes(eDataType);
433 8 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
434 8 : *pnPixelSpace *= m_poGDS->nBands;
435 8 : *pnLineSpace = nLineSize;
436 8 : return pVMem;
437 : }
438 : }
439 :
440 12 : VSILFILE *fp = VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF));
441 :
442 12 : vsi_l_offset nLength = static_cast<vsi_l_offset>(nRasterYSize) * nLineSize;
443 :
444 24 : if (!(CPLIsVirtualMemFileMapAvailable() &&
445 12 : VSIFGetNativeFileDescriptorL(fp) != nullptr &&
446 : #if SIZEOF_VOIDP == 4
447 : nLength == static_cast<size_t>(nLength) &&
448 : #endif
449 10 : m_poGDS->m_nCompression == COMPRESSION_NONE &&
450 10 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK ||
451 0 : m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB ||
452 0 : m_poGDS->m_nPhotometric == PHOTOMETRIC_PALETTE) &&
453 10 : m_poGDS->m_nBitsPerSample == GDALGetDataTypeSizeBits(eDataType) &&
454 10 : !TIFFIsTiled(m_poGDS->m_hTIFF) &&
455 10 : !TIFFIsByteSwapped(m_poGDS->m_hTIFF)))
456 : {
457 2 : return nullptr;
458 : }
459 :
460 : // Make sure that TIFFTAG_STRIPOFFSETS is up-to-date.
461 10 : if (m_poGDS->GetAccess() == GA_Update)
462 : {
463 7 : m_poGDS->FlushCache(false);
464 7 : VSI_TIFFFlushBufferedWrite(TIFFClientdata(m_poGDS->m_hTIFF));
465 : }
466 :
467 : // Get strip offsets.
468 10 : toff_t *panTIFFOffsets = nullptr;
469 10 : if (!TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_STRIPOFFSETS,
470 20 : &panTIFFOffsets) ||
471 10 : panTIFFOffsets == nullptr)
472 : {
473 0 : return nullptr;
474 : }
475 :
476 10 : GPtrDiff_t nBlockSize = static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize *
477 10 : GDALGetDataTypeSizeBytes(eDataType);
478 10 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
479 4 : nBlockSize *= m_poGDS->nBands;
480 :
481 10 : int nBlocks = m_poGDS->m_nBlocksPerBand;
482 10 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
483 6 : nBlocks *= m_poGDS->nBands;
484 10 : int i = 0; // Used after for.
485 103 : for (; i < nBlocks; ++i)
486 : {
487 100 : if (panTIFFOffsets[i] != 0)
488 7 : break;
489 : }
490 10 : if (i == nBlocks)
491 : {
492 : // All zeroes.
493 3 : if (m_poGDS->eAccess == GA_Update)
494 : {
495 : // Initialize the file with empty blocks so that the file has
496 : // the appropriate size.
497 :
498 3 : toff_t *panByteCounts = nullptr;
499 3 : if (!TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_STRIPBYTECOUNTS,
500 6 : &panByteCounts) ||
501 3 : panByteCounts == nullptr)
502 : {
503 0 : return nullptr;
504 : }
505 3 : if (VSIFSeekL(fp, 0, SEEK_END) != 0)
506 0 : return nullptr;
507 3 : vsi_l_offset nBaseOffset = VSIFTellL(fp);
508 :
509 : // Just write one tile with libtiff to put it in appropriate state.
510 : GByte *pabyData =
511 3 : static_cast<GByte *>(VSI_CALLOC_VERBOSE(1, nBlockSize));
512 3 : if (pabyData == nullptr)
513 : {
514 0 : return nullptr;
515 : }
516 3 : const auto ret = TIFFWriteEncodedStrip(m_poGDS->m_hTIFF, 0,
517 : pabyData, nBlockSize);
518 3 : VSI_TIFFFlushBufferedWrite(TIFFClientdata(m_poGDS->m_hTIFF));
519 3 : VSIFree(pabyData);
520 3 : if (ret != nBlockSize)
521 : {
522 0 : return nullptr;
523 : }
524 3 : CPLAssert(panTIFFOffsets[0] == nBaseOffset);
525 3 : CPLAssert(panByteCounts[0] == static_cast<toff_t>(nBlockSize));
526 :
527 : // Now simulate the writing of other blocks.
528 3 : assert(nBlocks > 0);
529 3 : assert(static_cast<vsi_l_offset>(nBlockSize) <
530 : std::numeric_limits<vsi_l_offset>::max() / nBlocks);
531 3 : const vsi_l_offset nDataSize =
532 3 : static_cast<vsi_l_offset>(nBlockSize) * nBlocks;
533 3 : if (VSIFTruncateL(fp, nBaseOffset + nDataSize) != 0)
534 0 : return nullptr;
535 :
536 93 : for (i = 1; i < nBlocks; ++i)
537 : {
538 90 : panTIFFOffsets[i] =
539 90 : nBaseOffset + i * static_cast<toff_t>(nBlockSize);
540 90 : panByteCounts[i] = nBlockSize;
541 : }
542 : }
543 : else
544 : {
545 0 : CPLDebug("GTiff", "Sparse files not supported in file mapping");
546 0 : return nullptr;
547 : }
548 : }
549 :
550 10 : GIntBig nBlockSpacing = 0;
551 10 : bool bCompatibleSpacing = true;
552 10 : toff_t nPrevOffset = 0;
553 229 : for (i = 0; i < m_poGDS->m_nBlocksPerBand; ++i)
554 : {
555 219 : toff_t nCurOffset = 0;
556 219 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
557 96 : nCurOffset =
558 96 : panTIFFOffsets[m_poGDS->m_nBlocksPerBand * (nBand - 1) + i];
559 : else
560 123 : nCurOffset = panTIFFOffsets[i];
561 219 : if (nCurOffset == 0)
562 : {
563 0 : bCompatibleSpacing = false;
564 0 : break;
565 : }
566 219 : if (i > 0)
567 : {
568 209 : const GIntBig nCurSpacing = nCurOffset - nPrevOffset;
569 209 : if (i == 1)
570 : {
571 10 : if (nCurSpacing !=
572 10 : static_cast<GIntBig>(nBlockYSize) * nLineSize)
573 : {
574 0 : bCompatibleSpacing = false;
575 0 : break;
576 : }
577 10 : nBlockSpacing = nCurSpacing;
578 : }
579 199 : else if (nBlockSpacing != nCurSpacing)
580 : {
581 0 : bCompatibleSpacing = false;
582 0 : break;
583 : }
584 : }
585 219 : nPrevOffset = nCurOffset;
586 : }
587 :
588 10 : if (!bCompatibleSpacing)
589 : {
590 0 : return nullptr;
591 : }
592 :
593 10 : vsi_l_offset nOffset = 0;
594 10 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
595 : {
596 4 : CPLAssert(m_poGDS->m_pBaseMapping == nullptr);
597 4 : nOffset = panTIFFOffsets[0];
598 : }
599 : else
600 : {
601 6 : nOffset = panTIFFOffsets[m_poGDS->m_nBlocksPerBand * (nBand - 1)];
602 : }
603 10 : CPLVirtualMem *pVMem = CPLVirtualMemFileMapNew(
604 : fp, nOffset, nLength,
605 : eRWFlag == GF_Write ? VIRTUALMEM_READWRITE : VIRTUALMEM_READONLY,
606 : nullptr, nullptr);
607 10 : if (pVMem == nullptr)
608 : {
609 0 : return nullptr;
610 : }
611 :
612 10 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
613 : {
614 : // TODO(schwehr): Revisit this block.
615 4 : m_poGDS->m_pBaseMapping = pVMem;
616 4 : pVMem = GetVirtualMemAutoInternal(eRWFlag, pnPixelSpace, pnLineSpace,
617 : papszOptions);
618 : // Drop ref on base mapping.
619 4 : CPLVirtualMemFree(m_poGDS->m_pBaseMapping);
620 4 : if (pVMem == nullptr)
621 0 : m_poGDS->m_pBaseMapping = nullptr;
622 : }
623 : else
624 : {
625 6 : *pnPixelSpace = GDALGetDataTypeSizeBytes(eDataType);
626 6 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
627 0 : *pnPixelSpace *= m_poGDS->nBands;
628 6 : *pnLineSpace = nLineSize;
629 : }
630 10 : return pVMem;
631 : }
632 :
633 : /************************************************************************/
634 : /* IGetDataCoverageStatus() */
635 : /************************************************************************/
636 :
637 815 : int GTiffRasterBand::IGetDataCoverageStatus(int nXOff, int nYOff, int nXSize,
638 : int nYSize, int nMaskFlagStop,
639 : double *pdfDataPct)
640 : {
641 815 : if (eAccess == GA_Update)
642 91 : m_poGDS->FlushCache(false);
643 :
644 815 : const int iXBlockStart = nXOff / nBlockXSize;
645 815 : const int iXBlockEnd = (nXOff + nXSize - 1) / nBlockXSize;
646 815 : const int iYBlockStart = nYOff / nBlockYSize;
647 815 : const int iYBlockEnd = (nYOff + nYSize - 1) / nBlockYSize;
648 815 : int nStatus = 0;
649 815 : VSILFILE *fp = VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF));
650 815 : GIntBig nPixelsData = 0;
651 2413 : for (int iY = iYBlockStart; iY <= iYBlockEnd; ++iY)
652 : {
653 4223 : for (int iX = iXBlockStart; iX <= iXBlockEnd; ++iX)
654 : {
655 2625 : const int nBlockIdBand0 = iX + iY * nBlocksPerRow;
656 2625 : int nBlockId = nBlockIdBand0;
657 2625 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
658 109 : nBlockId =
659 109 : nBlockIdBand0 + (nBand - 1) * m_poGDS->m_nBlocksPerBand;
660 2625 : vsi_l_offset nOffset = 0;
661 2625 : vsi_l_offset nLength = 0;
662 2625 : bool bHasData = false;
663 2625 : bool bError = false;
664 2625 : if (!m_poGDS->IsBlockAvailable(nBlockId, &nOffset, &nLength,
665 : &bError))
666 : {
667 1866 : if (bError)
668 753 : return GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED;
669 1866 : nStatus |= GDAL_DATA_COVERAGE_STATUS_EMPTY;
670 : }
671 : else
672 : {
673 759 : if (m_poGDS->m_nCompression == COMPRESSION_NONE &&
674 668 : m_poGDS->eAccess == GA_ReadOnly &&
675 630 : ((!m_bNoDataSet && !m_bNoDataSetAsInt64 &&
676 630 : !m_bNoDataSetAsUInt64) ||
677 0 : (m_bNoDataSet && m_dfNoDataValue == 0.0) ||
678 0 : (m_bNoDataSetAsInt64 && m_nNoDataValueInt64 == 0) ||
679 0 : (m_bNoDataSetAsUInt64 && m_nNoDataValueUInt64 == 0)))
680 : {
681 : VSIRangeStatus eStatus =
682 630 : VSIFGetRangeStatusL(fp, nOffset, nLength);
683 630 : if (eStatus == VSI_RANGE_STATUS_HOLE)
684 : {
685 0 : nStatus |= GDAL_DATA_COVERAGE_STATUS_EMPTY;
686 : }
687 : else
688 : {
689 630 : bHasData = true;
690 630 : }
691 : }
692 : else
693 : {
694 129 : bHasData = true;
695 : }
696 : }
697 2625 : if (bHasData)
698 : {
699 759 : const int nXBlockRight =
700 759 : (iX * nBlockXSize > INT_MAX - nBlockXSize)
701 759 : ? INT_MAX
702 759 : : (iX + 1) * nBlockXSize;
703 759 : const int nYBlockBottom =
704 759 : (iY * nBlockYSize > INT_MAX - nBlockYSize)
705 759 : ? INT_MAX
706 759 : : (iY + 1) * nBlockYSize;
707 :
708 1518 : nPixelsData += (static_cast<GIntBig>(
709 759 : std::min(nXBlockRight, nXOff + nXSize)) -
710 759 : std::max(iX * nBlockXSize, nXOff)) *
711 759 : (std::min(nYBlockBottom, nYOff + nYSize) -
712 759 : std::max(iY * nBlockYSize, nYOff));
713 759 : nStatus |= GDAL_DATA_COVERAGE_STATUS_DATA;
714 : }
715 2625 : if (nMaskFlagStop != 0 && (nMaskFlagStop & nStatus) != 0)
716 : {
717 753 : if (pdfDataPct)
718 0 : *pdfDataPct = -1.0;
719 753 : return nStatus;
720 : }
721 : }
722 : }
723 62 : if (pdfDataPct)
724 8 : *pdfDataPct =
725 8 : 100.0 * nPixelsData / (static_cast<GIntBig>(nXSize) * nYSize);
726 62 : return nStatus;
727 : }
728 :
729 : /************************************************************************/
730 : /* IReadBlock() */
731 : /************************************************************************/
732 :
733 2205860 : CPLErr GTiffRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
734 :
735 : {
736 2205860 : m_poGDS->Crystalize();
737 :
738 2205830 : GPtrDiff_t nBlockBufSize = 0;
739 2205830 : if (TIFFIsTiled(m_poGDS->m_hTIFF))
740 : {
741 56095 : nBlockBufSize = static_cast<GPtrDiff_t>(TIFFTileSize(m_poGDS->m_hTIFF));
742 : }
743 : else
744 : {
745 2149740 : CPLAssert(nBlockXOff == 0);
746 : nBlockBufSize =
747 2149740 : static_cast<GPtrDiff_t>(TIFFStripSize(m_poGDS->m_hTIFF));
748 : }
749 :
750 2205800 : const int nBlockId = ComputeBlockId(nBlockXOff, nBlockYOff);
751 :
752 : /* -------------------------------------------------------------------- */
753 : /* The bottom most partial tiles and strips are sometimes only */
754 : /* partially encoded. This code reduces the requested data so */
755 : /* an error won't be reported in this case. (#1179) */
756 : /* -------------------------------------------------------------------- */
757 2205820 : auto nBlockReqSize = nBlockBufSize;
758 :
759 2205820 : if (nBlockYOff * nBlockYSize > nRasterYSize - nBlockYSize)
760 : {
761 6206 : nBlockReqSize =
762 6206 : (nBlockBufSize / nBlockYSize) *
763 6206 : (nBlockYSize -
764 : static_cast<int>(
765 6206 : (static_cast<GIntBig>(nBlockYOff + 1) * nBlockYSize) %
766 6206 : nRasterYSize));
767 : }
768 :
769 : /* -------------------------------------------------------------------- */
770 : /* Handle the case of a strip or tile that doesn't exist yet. */
771 : /* Just set to zeros and return. */
772 : /* -------------------------------------------------------------------- */
773 2205820 : vsi_l_offset nOffset = 0;
774 2205820 : bool bErrOccurred = false;
775 4375770 : if (nBlockId != m_poGDS->m_nLoadedBlock &&
776 2169930 : !m_poGDS->IsBlockAvailable(nBlockId, &nOffset, nullptr, &bErrOccurred))
777 : {
778 50288 : NullBlock(pImage);
779 50288 : if (bErrOccurred)
780 1 : return CE_Failure;
781 50287 : return CE_None;
782 : }
783 :
784 2155550 : if (m_poGDS->m_bStreamingIn &&
785 10936 : !(m_poGDS->nBands > 1 &&
786 10423 : m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG &&
787 10048 : nBlockId == m_poGDS->m_nLoadedBlock))
788 : {
789 3436 : if (nOffset < VSIFTellL(m_poGDS->m_fpL))
790 : {
791 2000 : ReportError(CE_Failure, CPLE_NotSupported,
792 : "Trying to load block %d at offset " CPL_FRMT_GUIB
793 : " whereas current pos is " CPL_FRMT_GUIB
794 : " (backward read not supported)",
795 : nBlockId, static_cast<GUIntBig>(nOffset),
796 1000 : static_cast<GUIntBig>(VSIFTellL(m_poGDS->m_fpL)));
797 1000 : return CE_Failure;
798 : }
799 : }
800 :
801 : /* -------------------------------------------------------------------- */
802 : /* Handle simple case (separate, onesampleperpixel) */
803 : /* -------------------------------------------------------------------- */
804 2154550 : CPLErr eErr = CE_None;
805 2154550 : if (m_poGDS->nBands == 1 ||
806 110348 : m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
807 : {
808 2056080 : if (nBlockReqSize < nBlockBufSize)
809 2472 : memset(pImage, 0, nBlockBufSize);
810 :
811 2056080 : if (!m_poGDS->ReadStrile(nBlockId, pImage, nBlockReqSize))
812 : {
813 62 : memset(pImage, 0, nBlockBufSize);
814 62 : return CE_Failure;
815 : }
816 : }
817 : else
818 : {
819 : /* --------------------------------------------------------------------
820 : */
821 : /* Load desired block */
822 : /* --------------------------------------------------------------------
823 : */
824 98468 : eErr = m_poGDS->LoadBlockBuf(nBlockId);
825 98488 : if (eErr != CE_None)
826 : {
827 41 : memset(pImage, 0,
828 82 : static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize *
829 41 : GDALGetDataTypeSizeBytes(eDataType));
830 41 : return eErr;
831 : }
832 :
833 98447 : bool bDoCopyWords = true;
834 64058 : if (nBand == 1 && !m_poGDS->m_bLoadingOtherBands &&
835 58512 : eAccess == GA_ReadOnly &&
836 48843 : (m_poGDS->nBands == 3 || m_poGDS->nBands == 4) &&
837 48463 : ((eDataType == GDT_Byte && m_poGDS->m_nBitsPerSample == 8) ||
838 1303 : (eDataType == GDT_Int16 && m_poGDS->m_nBitsPerSample == 16) ||
839 162779 : (eDataType == GDT_UInt16 && m_poGDS->m_nBitsPerSample == 16)) &&
840 95717 : static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize *
841 47862 : GDALGetDataTypeSizeBytes(eDataType) <
842 47855 : GDALGetCacheMax64() / m_poGDS->nBands)
843 : {
844 47844 : bDoCopyWords = false;
845 : void *ppDestBuffers[4];
846 47844 : GDALRasterBlock *apoLockedBlocks[4] = {nullptr, nullptr, nullptr,
847 : nullptr};
848 202790 : for (int iBand = 1; iBand <= m_poGDS->nBands; ++iBand)
849 : {
850 154919 : if (iBand == nBand)
851 : {
852 47843 : ppDestBuffers[iBand - 1] = pImage;
853 : }
854 : else
855 : {
856 : GDALRasterBlock *poBlock =
857 107076 : m_poGDS->GetRasterBand(iBand)->GetLockedBlockRef(
858 107079 : nBlockXOff, nBlockYOff, true);
859 107102 : if (poBlock == nullptr)
860 : {
861 0 : bDoCopyWords = true;
862 0 : break;
863 : }
864 107102 : ppDestBuffers[iBand - 1] = poBlock->GetDataRef();
865 107103 : apoLockedBlocks[iBand - 1] = poBlock;
866 : }
867 : }
868 47871 : if (!bDoCopyWords)
869 : {
870 47859 : GDALDeinterleave(m_poGDS->m_pabyBlockBuf, eDataType,
871 47859 : m_poGDS->nBands, ppDestBuffers, eDataType,
872 47859 : static_cast<size_t>(nBlockXSize) *
873 47859 : nBlockYSize);
874 : }
875 202821 : for (int iBand = 1; iBand <= m_poGDS->nBands; ++iBand)
876 : {
877 154963 : if (apoLockedBlocks[iBand - 1])
878 : {
879 107106 : apoLockedBlocks[iBand - 1]->DropLock();
880 : }
881 : }
882 : }
883 :
884 98449 : if (bDoCopyWords)
885 : {
886 50591 : const int nWordBytes = m_poGDS->m_nBitsPerSample / 8;
887 50591 : GByte *pabyImage =
888 50591 : m_poGDS->m_pabyBlockBuf + (nBand - 1) * nWordBytes;
889 :
890 50591 : GDALCopyWords64(pabyImage, eDataType, m_poGDS->nBands * nWordBytes,
891 : pImage, eDataType, nWordBytes,
892 50591 : static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize);
893 :
894 50591 : eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff);
895 : }
896 : }
897 :
898 2154450 : CacheMaskForBlock(nBlockXOff, nBlockYOff);
899 :
900 2154480 : return eErr;
901 : }
902 :
903 : /************************************************************************/
904 : /* CacheMaskForBlock() */
905 : /************************************************************************/
906 :
907 2156890 : void GTiffRasterBand::CacheMaskForBlock(int nBlockXOff, int nBlockYOff)
908 :
909 : {
910 : // Preload mask data if layout compatible and we have cached ranges
911 2156980 : if (m_poGDS->m_bMaskInterleavedWithImagery && m_poGDS->m_poMaskDS &&
912 109 : VSI_TIFFHasCachedRanges(TIFFClientdata(m_poGDS->m_hTIFF)))
913 : {
914 98 : auto poBand = cpl::down_cast<GTiffRasterBand *>(
915 98 : m_poGDS->m_poMaskDS->GetRasterBand(1));
916 294 : if (m_poGDS->m_poMaskDS->m_oCacheStrileToOffsetByteCount.contains(
917 98 : poBand->ComputeBlockId(nBlockXOff, nBlockYOff)))
918 : {
919 : GDALRasterBlock *poBlock =
920 94 : poBand->GetLockedBlockRef(nBlockXOff, nBlockYOff);
921 94 : if (poBlock)
922 94 : poBlock->DropLock();
923 : }
924 : }
925 2156870 : }
926 :
927 : /************************************************************************/
928 : /* FillCacheForOtherBands() */
929 : /************************************************************************/
930 :
931 50805 : CPLErr GTiffRasterBand::FillCacheForOtherBands(int nBlockXOff, int nBlockYOff)
932 :
933 : {
934 : /* -------------------------------------------------------------------- */
935 : /* In the fairly common case of pixel interleaved 8bit data */
936 : /* that is multi-band, lets push the rest of the data into the */
937 : /* block cache too, to avoid (hopefully) having to redecode it. */
938 : /* */
939 : /* Our following logic actually depends on the fact that the */
940 : /* this block is already loaded, so subsequent calls will end */
941 : /* up back in this method and pull from the loaded block. */
942 : /* */
943 : /* Be careful not entering this portion of code from */
944 : /* the other bands, otherwise we'll get very deep nested calls */
945 : /* and O(nBands^2) performance ! */
946 : /* */
947 : /* If there are many bands and the block cache size is not big */
948 : /* enough to accommodate the size of all the blocks, don't enter */
949 : /* -------------------------------------------------------------------- */
950 50805 : CPLErr eErr = CE_None;
951 152415 : if (m_poGDS->nBands != 1 &&
952 50805 : m_poGDS->nBands <
953 50803 : 128 && // avoid caching for datasets with too many bands
954 114837 : !m_poGDS->m_bLoadingOtherBands &&
955 26454 : static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize *
956 13227 : GDALGetDataTypeSizeBytes(eDataType) <
957 13227 : GDALGetCacheMax64() / m_poGDS->nBands)
958 : {
959 13227 : m_poGDS->m_bLoadingOtherBands = true;
960 :
961 54994 : for (int iOtherBand = 1; iOtherBand <= m_poGDS->nBands; ++iOtherBand)
962 : {
963 41767 : if (iOtherBand == nBand)
964 13227 : continue;
965 :
966 : GDALRasterBlock *poBlock =
967 28540 : m_poGDS->GetRasterBand(iOtherBand)
968 28540 : ->GetLockedBlockRef(nBlockXOff, nBlockYOff);
969 28540 : if (poBlock == nullptr)
970 : {
971 0 : eErr = CE_Failure;
972 0 : break;
973 : }
974 28540 : poBlock->DropLock();
975 : }
976 :
977 13227 : m_poGDS->m_bLoadingOtherBands = false;
978 : }
979 :
980 50805 : return eErr;
981 : }
982 :
983 : /************************************************************************/
984 : /* GetDescription() */
985 : /************************************************************************/
986 :
987 206052 : const char *GTiffRasterBand::GetDescription() const
988 : {
989 206052 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
990 :
991 206052 : return m_osDescription;
992 : }
993 :
994 : /************************************************************************/
995 : /* GetOffset() */
996 : /************************************************************************/
997 :
998 213464 : double GTiffRasterBand::GetOffset(int *pbSuccess)
999 :
1000 : {
1001 213464 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
1002 :
1003 213464 : if (pbSuccess)
1004 6932 : *pbSuccess = m_bHaveOffsetScale;
1005 213464 : return m_dfOffset;
1006 : }
1007 :
1008 : /************************************************************************/
1009 : /* GetScale() */
1010 : /************************************************************************/
1011 :
1012 213467 : double GTiffRasterBand::GetScale(int *pbSuccess)
1013 :
1014 : {
1015 213467 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
1016 :
1017 213467 : if (pbSuccess)
1018 6935 : *pbSuccess = m_bHaveOffsetScale;
1019 213467 : return m_dfScale;
1020 : }
1021 :
1022 : /************************************************************************/
1023 : /* GetUnitType() */
1024 : /************************************************************************/
1025 :
1026 205256 : const char *GTiffRasterBand::GetUnitType()
1027 :
1028 : {
1029 205256 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
1030 205256 : if (m_osUnitType.empty())
1031 : {
1032 205177 : m_poGDS->LookForProjection();
1033 205177 : if (m_poGDS->m_pszVertUnit)
1034 9 : return m_poGDS->m_pszVertUnit;
1035 : }
1036 :
1037 205247 : return m_osUnitType.c_str();
1038 : }
1039 :
1040 : /************************************************************************/
1041 : /* GetMetadataDomainList() */
1042 : /************************************************************************/
1043 :
1044 12 : char **GTiffRasterBand::GetMetadataDomainList()
1045 : {
1046 12 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
1047 :
1048 12 : return CSLDuplicate(m_oGTiffMDMD.GetDomainList());
1049 : }
1050 :
1051 : /************************************************************************/
1052 : /* GetMetadata() */
1053 : /************************************************************************/
1054 :
1055 16117 : char **GTiffRasterBand::GetMetadata(const char *pszDomain)
1056 :
1057 : {
1058 16117 : if (pszDomain == nullptr || !EQUAL(pszDomain, "IMAGE_STRUCTURE"))
1059 : {
1060 15953 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
1061 : }
1062 :
1063 16117 : return m_oGTiffMDMD.GetMetadata(pszDomain);
1064 : }
1065 :
1066 : /************************************************************************/
1067 : /* GetMetadataItem() */
1068 : /************************************************************************/
1069 :
1070 31475 : const char *GTiffRasterBand::GetMetadataItem(const char *pszName,
1071 : const char *pszDomain)
1072 :
1073 : {
1074 31475 : if (pszDomain == nullptr || !EQUAL(pszDomain, "IMAGE_STRUCTURE"))
1075 : {
1076 8245 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
1077 : }
1078 :
1079 31475 : if (pszName != nullptr && pszDomain != nullptr && EQUAL(pszDomain, "TIFF"))
1080 : {
1081 5259 : int nBlockXOff = 0;
1082 5259 : int nBlockYOff = 0;
1083 :
1084 5259 : if (EQUAL(pszName, "JPEGTABLES"))
1085 : {
1086 11 : uint32_t nJPEGTableSize = 0;
1087 11 : void *pJPEGTable = nullptr;
1088 11 : if (TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_JPEGTABLES,
1089 11 : &nJPEGTableSize, &pJPEGTable) != 1 ||
1090 11 : pJPEGTable == nullptr || nJPEGTableSize > INT_MAX)
1091 : {
1092 0 : return nullptr;
1093 : }
1094 11 : char *const pszHex = CPLBinaryToHex(
1095 : nJPEGTableSize, static_cast<const GByte *>(pJPEGTable));
1096 11 : const char *pszReturn = CPLSPrintf("%s", pszHex);
1097 11 : CPLFree(pszHex);
1098 :
1099 11 : return pszReturn;
1100 : }
1101 :
1102 5248 : if (EQUAL(pszName, "IFD_OFFSET"))
1103 : {
1104 186 : return CPLSPrintf(CPL_FRMT_GUIB,
1105 93 : static_cast<GUIntBig>(m_poGDS->m_nDirOffset));
1106 : }
1107 :
1108 5155 : if (sscanf(pszName, "BLOCK_OFFSET_%d_%d", &nBlockXOff, &nBlockYOff) ==
1109 : 2)
1110 : {
1111 4422 : if (nBlockXOff < 0 || nBlockXOff >= nBlocksPerRow ||
1112 4421 : nBlockYOff < 0 || nBlockYOff >= nBlocksPerColumn)
1113 19 : return nullptr;
1114 :
1115 4403 : int nBlockId = nBlockYOff * nBlocksPerRow + nBlockXOff;
1116 4403 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
1117 : {
1118 3571 : nBlockId += (nBand - 1) * m_poGDS->m_nBlocksPerBand;
1119 : }
1120 :
1121 4403 : vsi_l_offset nOffset = 0;
1122 4403 : if (!m_poGDS->IsBlockAvailable(nBlockId, &nOffset, nullptr,
1123 : nullptr))
1124 : {
1125 190 : return nullptr;
1126 : }
1127 :
1128 4213 : return CPLSPrintf(CPL_FRMT_GUIB, static_cast<GUIntBig>(nOffset));
1129 : }
1130 :
1131 733 : if (sscanf(pszName, "BLOCK_SIZE_%d_%d", &nBlockXOff, &nBlockYOff) == 2)
1132 : {
1133 733 : if (nBlockXOff < 0 || nBlockXOff >= nBlocksPerRow ||
1134 732 : nBlockYOff < 0 || nBlockYOff >= nBlocksPerColumn)
1135 2 : return nullptr;
1136 :
1137 731 : int nBlockId = nBlockYOff * nBlocksPerRow + nBlockXOff;
1138 731 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
1139 : {
1140 244 : nBlockId += (nBand - 1) * m_poGDS->m_nBlocksPerBand;
1141 : }
1142 :
1143 731 : vsi_l_offset nByteCount = 0;
1144 731 : if (!m_poGDS->IsBlockAvailable(nBlockId, nullptr, &nByteCount,
1145 : nullptr))
1146 : {
1147 89 : return nullptr;
1148 : }
1149 :
1150 642 : return CPLSPrintf(CPL_FRMT_GUIB, static_cast<GUIntBig>(nByteCount));
1151 0 : }
1152 : }
1153 26216 : else if (pszName && pszDomain && EQUAL(pszDomain, "_DEBUG_"))
1154 : {
1155 131 : if (EQUAL(pszName, "HAS_BLOCK_CACHE"))
1156 131 : return HasBlockCache() ? "1" : "0";
1157 : }
1158 :
1159 26085 : const char *pszRet = m_oGTiffMDMD.GetMetadataItem(pszName, pszDomain);
1160 :
1161 26085 : if (pszRet == nullptr && eDataType == GDT_Byte && pszName && pszDomain &&
1162 23720 : EQUAL(pszDomain, "IMAGE_STRUCTURE") && EQUAL(pszName, "PIXELTYPE"))
1163 : {
1164 : // to get a chance of emitting the warning about this legacy usage
1165 5193 : pszRet = GDALRasterBand::GetMetadataItem(pszName, pszDomain);
1166 : }
1167 26085 : return pszRet;
1168 : }
1169 :
1170 : /************************************************************************/
1171 : /* GetColorInterpretation() */
1172 : /************************************************************************/
1173 :
1174 226220 : GDALColorInterp GTiffRasterBand::GetColorInterpretation()
1175 :
1176 : {
1177 226220 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
1178 :
1179 226220 : return m_eBandInterp;
1180 : }
1181 :
1182 : /************************************************************************/
1183 : /* GetColorTable() */
1184 : /************************************************************************/
1185 :
1186 11670 : GDALColorTable *GTiffRasterBand::GetColorTable()
1187 :
1188 : {
1189 11670 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
1190 :
1191 11670 : if (nBand == 1)
1192 9930 : return m_poGDS->m_poColorTable.get();
1193 :
1194 1740 : return nullptr;
1195 : }
1196 :
1197 : /************************************************************************/
1198 : /* GetNoDataValue() */
1199 : /************************************************************************/
1200 :
1201 817363 : double GTiffRasterBand::GetNoDataValue(int *pbSuccess)
1202 :
1203 : {
1204 817363 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
1205 :
1206 817317 : int bSuccess = FALSE;
1207 817317 : double dfNoDataValue = GDALPamRasterBand::GetNoDataValue(&bSuccess);
1208 817148 : if (bSuccess)
1209 : {
1210 4 : if (pbSuccess)
1211 4 : *pbSuccess = TRUE;
1212 :
1213 4 : return dfNoDataValue;
1214 : }
1215 :
1216 817144 : if (m_bNoDataSet)
1217 : {
1218 2301 : if (pbSuccess)
1219 2268 : *pbSuccess = TRUE;
1220 :
1221 2301 : return m_dfNoDataValue;
1222 : }
1223 :
1224 814843 : if (m_poGDS->m_bNoDataSet)
1225 : {
1226 422911 : if (pbSuccess)
1227 422757 : *pbSuccess = TRUE;
1228 :
1229 422911 : return m_poGDS->m_dfNoDataValue;
1230 : }
1231 :
1232 391932 : if (m_bNoDataSetAsInt64)
1233 : {
1234 0 : if (pbSuccess)
1235 0 : *pbSuccess = TRUE;
1236 :
1237 0 : return GDALGetNoDataValueCastToDouble(m_nNoDataValueInt64);
1238 : }
1239 :
1240 391932 : if (m_poGDS->m_bNoDataSetAsInt64)
1241 : {
1242 0 : if (pbSuccess)
1243 0 : *pbSuccess = TRUE;
1244 :
1245 0 : return GDALGetNoDataValueCastToDouble(m_poGDS->m_nNoDataValueInt64);
1246 : }
1247 :
1248 391932 : if (m_bNoDataSetAsUInt64)
1249 : {
1250 0 : if (pbSuccess)
1251 0 : *pbSuccess = TRUE;
1252 :
1253 0 : return GDALGetNoDataValueCastToDouble(m_nNoDataValueUInt64);
1254 : }
1255 :
1256 391932 : if (m_poGDS->m_bNoDataSetAsUInt64)
1257 : {
1258 0 : if (pbSuccess)
1259 0 : *pbSuccess = TRUE;
1260 :
1261 0 : return GDALGetNoDataValueCastToDouble(m_poGDS->m_nNoDataValueUInt64);
1262 : }
1263 :
1264 391932 : if (pbSuccess)
1265 392164 : *pbSuccess = FALSE;
1266 391932 : return dfNoDataValue;
1267 : }
1268 :
1269 : /************************************************************************/
1270 : /* GetNoDataValueAsInt64() */
1271 : /************************************************************************/
1272 :
1273 25 : int64_t GTiffRasterBand::GetNoDataValueAsInt64(int *pbSuccess)
1274 :
1275 : {
1276 25 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
1277 :
1278 25 : if (eDataType == GDT_UInt64)
1279 : {
1280 0 : CPLError(CE_Failure, CPLE_AppDefined,
1281 : "GetNoDataValueAsUInt64() should be called instead");
1282 0 : if (pbSuccess)
1283 0 : *pbSuccess = FALSE;
1284 0 : return GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
1285 : }
1286 25 : if (eDataType != GDT_Int64)
1287 : {
1288 0 : CPLError(CE_Failure, CPLE_AppDefined,
1289 : "GetNoDataValue() should be called instead");
1290 0 : if (pbSuccess)
1291 0 : *pbSuccess = FALSE;
1292 0 : return GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
1293 : }
1294 :
1295 25 : int bSuccess = FALSE;
1296 : const auto nNoDataValue =
1297 25 : GDALPamRasterBand::GetNoDataValueAsInt64(&bSuccess);
1298 25 : if (bSuccess)
1299 : {
1300 0 : if (pbSuccess)
1301 0 : *pbSuccess = TRUE;
1302 :
1303 0 : return nNoDataValue;
1304 : }
1305 :
1306 25 : if (m_bNoDataSetAsInt64)
1307 : {
1308 2 : if (pbSuccess)
1309 2 : *pbSuccess = TRUE;
1310 :
1311 2 : return m_nNoDataValueInt64;
1312 : }
1313 :
1314 23 : if (m_poGDS->m_bNoDataSetAsInt64)
1315 : {
1316 7 : if (pbSuccess)
1317 6 : *pbSuccess = TRUE;
1318 :
1319 7 : return m_poGDS->m_nNoDataValueInt64;
1320 : }
1321 :
1322 16 : if (pbSuccess)
1323 16 : *pbSuccess = FALSE;
1324 16 : return nNoDataValue;
1325 : }
1326 :
1327 : /************************************************************************/
1328 : /* GetNoDataValueAsUInt64() */
1329 : /************************************************************************/
1330 :
1331 16 : uint64_t GTiffRasterBand::GetNoDataValueAsUInt64(int *pbSuccess)
1332 :
1333 : {
1334 16 : m_poGDS->LoadGeoreferencingAndPamIfNeeded();
1335 :
1336 16 : if (eDataType == GDT_Int64)
1337 : {
1338 0 : CPLError(CE_Failure, CPLE_AppDefined,
1339 : "GetNoDataValueAsInt64() should be called instead");
1340 0 : if (pbSuccess)
1341 0 : *pbSuccess = FALSE;
1342 0 : return GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
1343 : }
1344 16 : if (eDataType != GDT_UInt64)
1345 : {
1346 0 : CPLError(CE_Failure, CPLE_AppDefined,
1347 : "GetNoDataValue() should be called instead");
1348 0 : if (pbSuccess)
1349 0 : *pbSuccess = FALSE;
1350 0 : return GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
1351 : }
1352 :
1353 16 : int bSuccess = FALSE;
1354 : const auto nNoDataValue =
1355 16 : GDALPamRasterBand::GetNoDataValueAsUInt64(&bSuccess);
1356 16 : if (bSuccess)
1357 : {
1358 0 : if (pbSuccess)
1359 0 : *pbSuccess = TRUE;
1360 :
1361 0 : return nNoDataValue;
1362 : }
1363 :
1364 16 : if (m_bNoDataSetAsUInt64)
1365 : {
1366 0 : if (pbSuccess)
1367 0 : *pbSuccess = TRUE;
1368 :
1369 0 : return m_nNoDataValueUInt64;
1370 : }
1371 :
1372 16 : if (m_poGDS->m_bNoDataSetAsUInt64)
1373 : {
1374 7 : if (pbSuccess)
1375 6 : *pbSuccess = TRUE;
1376 :
1377 7 : return m_poGDS->m_nNoDataValueUInt64;
1378 : }
1379 :
1380 9 : if (pbSuccess)
1381 9 : *pbSuccess = FALSE;
1382 9 : return nNoDataValue;
1383 : }
1384 :
1385 : /************************************************************************/
1386 : /* GetOverviewCount() */
1387 : /************************************************************************/
1388 :
1389 655745 : int GTiffRasterBand::GetOverviewCount()
1390 :
1391 : {
1392 655745 : if (!m_poGDS->AreOverviewsEnabled())
1393 30 : return 0;
1394 :
1395 655715 : m_poGDS->ScanDirectories();
1396 :
1397 655715 : if (m_poGDS->m_nOverviewCount > 0)
1398 : {
1399 4993 : return m_poGDS->m_nOverviewCount;
1400 : }
1401 :
1402 650722 : const int nOverviewCount = GDALRasterBand::GetOverviewCount();
1403 650722 : if (nOverviewCount > 0)
1404 370 : return nOverviewCount;
1405 :
1406 : // Implicit JPEG overviews are normally hidden, except when doing
1407 : // IRasterIO() operations.
1408 650352 : if (m_poGDS->m_nJPEGOverviewVisibilityCounter)
1409 643432 : return m_poGDS->GetJPEGOverviewCount();
1410 :
1411 6920 : return 0;
1412 : }
1413 :
1414 : /************************************************************************/
1415 : /* GetOverview() */
1416 : /************************************************************************/
1417 :
1418 8660 : GDALRasterBand *GTiffRasterBand::GetOverview(int i)
1419 :
1420 : {
1421 8660 : m_poGDS->ScanDirectories();
1422 :
1423 8660 : if (m_poGDS->m_nOverviewCount > 0)
1424 : {
1425 : // Do we have internal overviews?
1426 8089 : if (i < 0 || i >= m_poGDS->m_nOverviewCount)
1427 8 : return nullptr;
1428 :
1429 8081 : return m_poGDS->m_papoOverviewDS[i]->GetRasterBand(nBand);
1430 : }
1431 :
1432 571 : GDALRasterBand *const poOvrBand = GDALRasterBand::GetOverview(i);
1433 571 : if (poOvrBand != nullptr)
1434 366 : return poOvrBand;
1435 :
1436 : // For consistency with GetOverviewCount(), we should also test
1437 : // m_nJPEGOverviewVisibilityCounter, but it is also convenient to be able
1438 : // to query them for testing purposes.
1439 205 : if (i >= 0 && i < m_poGDS->GetJPEGOverviewCount())
1440 164 : return m_poGDS->m_papoJPEGOverviewDS[i]->GetRasterBand(nBand);
1441 :
1442 41 : return nullptr;
1443 : }
1444 :
1445 : /************************************************************************/
1446 : /* GetMaskFlags() */
1447 : /************************************************************************/
1448 :
1449 18553 : int GTiffRasterBand::GetMaskFlags()
1450 : {
1451 18553 : m_poGDS->ScanDirectories();
1452 :
1453 18553 : if (m_poGDS->m_poExternalMaskDS != nullptr)
1454 : {
1455 0 : return GMF_PER_DATASET;
1456 : }
1457 :
1458 18553 : if (m_poGDS->m_poMaskDS != nullptr)
1459 : {
1460 204 : if (m_poGDS->m_poMaskDS->GetRasterCount() == 1)
1461 : {
1462 197 : return GMF_PER_DATASET;
1463 : }
1464 :
1465 7 : return 0;
1466 : }
1467 :
1468 18349 : if (m_poGDS->m_bIsOverview)
1469 : {
1470 392 : return m_poGDS->m_poBaseDS->GetRasterBand(nBand)->GetMaskFlags();
1471 : }
1472 :
1473 17957 : return GDALPamRasterBand::GetMaskFlags();
1474 : }
1475 :
1476 : /************************************************************************/
1477 : /* GetMaskBand() */
1478 : /************************************************************************/
1479 :
1480 121914 : GDALRasterBand *GTiffRasterBand::GetMaskBand()
1481 : {
1482 121914 : m_poGDS->ScanDirectories();
1483 :
1484 121009 : if (m_poGDS->m_poExternalMaskDS != nullptr)
1485 : {
1486 353 : return m_poGDS->m_poExternalMaskDS->GetRasterBand(1);
1487 : }
1488 :
1489 120656 : if (m_poGDS->m_poMaskDS != nullptr)
1490 : {
1491 679 : if (m_poGDS->m_poMaskDS->GetRasterCount() == 1)
1492 665 : return m_poGDS->m_poMaskDS->GetRasterBand(1);
1493 :
1494 14 : return m_poGDS->m_poMaskDS->GetRasterBand(nBand);
1495 : }
1496 :
1497 119977 : if (m_poGDS->m_bIsOverview)
1498 : {
1499 : GDALRasterBand *poBaseMask =
1500 116 : m_poGDS->m_poBaseDS->GetRasterBand(nBand)->GetMaskBand();
1501 116 : if (poBaseMask)
1502 : {
1503 116 : const int nOverviews = poBaseMask->GetOverviewCount();
1504 161 : for (int i = 0; i < nOverviews; i++)
1505 : {
1506 93 : GDALRasterBand *poOvr = poBaseMask->GetOverview(i);
1507 141 : if (poOvr && poOvr->GetXSize() == GetXSize() &&
1508 48 : poOvr->GetYSize() == GetYSize())
1509 : {
1510 48 : return poOvr;
1511 : }
1512 : }
1513 : }
1514 : }
1515 :
1516 119929 : return GDALPamRasterBand::GetMaskBand();
1517 : }
1518 :
1519 : /************************************************************************/
1520 : /* IsMaskBand() */
1521 : /************************************************************************/
1522 :
1523 9118 : bool GTiffRasterBand::IsMaskBand() const
1524 : {
1525 9149 : return (m_poGDS->m_poImageryDS != nullptr &&
1526 31 : m_poGDS->m_poImageryDS->m_poMaskDS == m_poGDS) ||
1527 16157 : m_eBandInterp == GCI_AlphaBand ||
1528 16126 : m_poGDS->GetMetadataItem("INTERNAL_MASK_FLAGS_1") != nullptr;
1529 : }
1530 :
1531 : /************************************************************************/
1532 : /* GetMaskValueRange() */
1533 : /************************************************************************/
1534 :
1535 0 : GDALMaskValueRange GTiffRasterBand::GetMaskValueRange() const
1536 : {
1537 0 : if (!IsMaskBand())
1538 0 : return GMVR_UNKNOWN;
1539 0 : if (m_poGDS->m_nBitsPerSample == 1)
1540 0 : return m_poGDS->m_bPromoteTo8Bits ? GMVR_0_AND_255_ONLY
1541 0 : : GMVR_0_AND_1_ONLY;
1542 0 : return GMVR_UNKNOWN;
1543 : }
|