Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GeoTIFF Driver
4 : * Purpose: GDAL GeoTIFF support.
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 "cpl_port.h" // Must be first.
15 :
16 : #include "gtiff.h"
17 :
18 : #include "tiff_common.h"
19 :
20 : #include "cpl_conv.h"
21 : #include "cpl_error.h"
22 : #include "gdal.h"
23 : #include "gdal_mdreader.h" // RPC_xxx
24 : #include "gtiffdataset.h"
25 : #include "tiffio.h"
26 : #include "tif_jxl.h"
27 : #include "xtiffio.h"
28 : #include <cctype>
29 : #include <cmath>
30 :
31 : // Needed to expose WEBP_LOSSLESS option
32 : #ifdef WEBP_SUPPORT
33 : #include "webp/encode.h"
34 : #endif
35 :
36 : #ifdef LERC_SUPPORT
37 : #include "Lerc_c_api.h"
38 : #endif
39 :
40 : #define STRINGIFY(x) #x
41 : #define XSTRINGIFY(x) STRINGIFY(x)
42 :
43 : static thread_local bool bThreadLocalInExternalOvr = false;
44 :
45 : static thread_local int gnThreadLocalLibtiffError = 0;
46 :
47 4298180 : int >IFFGetThreadLocalLibtiffError()
48 : {
49 4298180 : return gnThreadLocalLibtiffError;
50 : }
51 :
52 : /************************************************************************/
53 : /* GTIFFSupportsPredictor() */
54 : /************************************************************************/
55 :
56 65107 : bool GTIFFSupportsPredictor(int nCompression)
57 : {
58 51888 : return nCompression == COMPRESSION_LZW ||
59 116995 : nCompression == COMPRESSION_ADOBE_DEFLATE ||
60 65107 : nCompression == COMPRESSION_ZSTD;
61 : }
62 :
63 : /************************************************************************/
64 : /* GTIFFSetThreadLocalInExternalOvr() */
65 : /************************************************************************/
66 :
67 438 : void GTIFFSetThreadLocalInExternalOvr(bool b)
68 : {
69 438 : bThreadLocalInExternalOvr = b;
70 438 : }
71 :
72 : /************************************************************************/
73 : /* GTIFFGetOverviewBlockSize() */
74 : /************************************************************************/
75 :
76 571 : void GTIFFGetOverviewBlockSize(GDALRasterBandH hBand, int *pnBlockXSize,
77 : int *pnBlockYSize, CSLConstList papszOptions,
78 : const char *pszOptionKey)
79 : {
80 571 : const char *pszVal = nullptr;
81 571 : const char *pszValItem = nullptr;
82 571 : if (papszOptions && pszOptionKey)
83 : {
84 65 : pszVal = CSLFetchNameValue(papszOptions, pszOptionKey);
85 65 : if (pszVal)
86 1 : pszValItem = pszOptionKey;
87 : }
88 571 : if (!pszVal)
89 : {
90 570 : pszVal = CPLGetConfigOption("GDAL_TIFF_OVR_BLOCKSIZE", nullptr);
91 570 : if (pszVal)
92 8 : pszValItem = "GDAL_TIFF_OVR_BLOCKSIZE";
93 : }
94 571 : if (!pszVal)
95 : {
96 562 : GDALRasterBand *const poBand = GDALRasterBand::FromHandle(hBand);
97 562 : poBand->GetBlockSize(pnBlockXSize, pnBlockYSize);
98 334 : if (*pnBlockXSize != *pnBlockYSize || *pnBlockXSize < 64 ||
99 896 : *pnBlockXSize > 4096 || !CPLIsPowerOfTwo(*pnBlockXSize))
100 : {
101 442 : *pnBlockXSize = *pnBlockYSize = 128;
102 : }
103 : }
104 : else
105 : {
106 9 : int nOvrBlockSize = atoi(pszVal);
107 18 : if (nOvrBlockSize < 64 || nOvrBlockSize > 4096 ||
108 9 : !CPLIsPowerOfTwo(nOvrBlockSize))
109 : {
110 0 : CPLErrorOnce(CE_Warning, CPLE_NotSupported,
111 : "Wrong value for %s : %s. "
112 : "Should be a power of 2 between 64 and 4096. "
113 : "Defaulting to 128",
114 : pszValItem, pszVal);
115 0 : nOvrBlockSize = 128;
116 : }
117 :
118 9 : *pnBlockXSize = nOvrBlockSize;
119 9 : *pnBlockYSize = nOvrBlockSize;
120 : }
121 571 : }
122 :
123 : /************************************************************************/
124 : /* GTIFFSetJpegQuality() */
125 : /* Called by GTIFFBuildOverviews() to set the jpeg quality on the IFD */
126 : /* of the .ovr file. */
127 : /************************************************************************/
128 :
129 4 : void GTIFFSetJpegQuality(GDALDatasetH hGTIFFDS, int nJpegQuality)
130 : {
131 4 : CPLAssert(
132 : EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
133 :
134 4 : GTiffDataset *const poDS = static_cast<GTiffDataset *>(hGTIFFDS);
135 4 : poDS->m_nJpegQuality = static_cast<signed char>(nJpegQuality);
136 :
137 4 : poDS->ScanDirectories();
138 :
139 7 : for (int i = 0; i < poDS->m_nOverviewCount; ++i)
140 3 : poDS->m_papoOverviewDS[i]->m_nJpegQuality = poDS->m_nJpegQuality;
141 4 : }
142 :
143 : /************************************************************************/
144 : /* GTIFFSetWebPLevel() */
145 : /* Called by GTIFFBuildOverviews() to set the jpeg quality on the IFD */
146 : /* of the .ovr file. */
147 : /************************************************************************/
148 :
149 3 : void GTIFFSetWebPLevel(GDALDatasetH hGTIFFDS, int nWebpLevel)
150 : {
151 3 : CPLAssert(
152 : EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
153 :
154 3 : GTiffDataset *const poDS = static_cast<GTiffDataset *>(hGTIFFDS);
155 3 : poDS->m_nWebPLevel = static_cast<signed char>(nWebpLevel);
156 :
157 3 : poDS->ScanDirectories();
158 :
159 6 : for (int i = 0; i < poDS->m_nOverviewCount; ++i)
160 3 : poDS->m_papoOverviewDS[i]->m_nWebPLevel = poDS->m_nWebPLevel;
161 3 : }
162 :
163 : /************************************************************************/
164 : /* GTIFFSetWebPLossless() */
165 : /* Called by GTIFFBuildOverviews() to set webp lossless on the IFD */
166 : /* of the .ovr file. */
167 : /************************************************************************/
168 :
169 1 : void GTIFFSetWebPLossless(GDALDatasetH hGTIFFDS, bool bWebpLossless)
170 : {
171 1 : CPLAssert(
172 : EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
173 :
174 1 : GTiffDataset *const poDS = static_cast<GTiffDataset *>(hGTIFFDS);
175 1 : poDS->m_bWebPLossless = bWebpLossless;
176 :
177 1 : poDS->ScanDirectories();
178 :
179 1 : for (int i = 0; i < poDS->m_nOverviewCount; ++i)
180 0 : poDS->m_papoOverviewDS[i]->m_bWebPLossless = poDS->m_bWebPLossless;
181 1 : }
182 :
183 : /************************************************************************/
184 : /* GTIFFSetJpegTablesMode() */
185 : /* Called by GTIFFBuildOverviews() to set the jpeg tables mode on the */
186 : /* of the .ovr file. */
187 : /************************************************************************/
188 :
189 0 : void GTIFFSetJpegTablesMode(GDALDatasetH hGTIFFDS, int nJpegTablesMode)
190 : {
191 0 : CPLAssert(
192 : EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
193 :
194 0 : GTiffDataset *const poDS = static_cast<GTiffDataset *>(hGTIFFDS);
195 0 : poDS->m_nJpegTablesMode = static_cast<signed char>(nJpegTablesMode);
196 :
197 0 : poDS->ScanDirectories();
198 :
199 0 : for (int i = 0; i < poDS->m_nOverviewCount; ++i)
200 0 : poDS->m_papoOverviewDS[i]->m_nJpegTablesMode = poDS->m_nJpegTablesMode;
201 0 : }
202 :
203 : /************************************************************************/
204 : /* GTIFFSetZLevel() */
205 : /* Called by GTIFFBuildOverviews() to set the deflate level on the IFD */
206 : /* of the .ovr file. */
207 : /************************************************************************/
208 :
209 2 : void GTIFFSetZLevel(GDALDatasetH hGTIFFDS, int nZLevel)
210 : {
211 2 : CPLAssert(
212 : EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
213 :
214 2 : GTiffDataset *const poDS = static_cast<GTiffDataset *>(hGTIFFDS);
215 2 : poDS->m_nZLevel = static_cast<signed char>(nZLevel);
216 :
217 2 : poDS->ScanDirectories();
218 :
219 4 : for (int i = 0; i < poDS->m_nOverviewCount; ++i)
220 2 : poDS->m_papoOverviewDS[i]->m_nZLevel = poDS->m_nZLevel;
221 2 : }
222 :
223 : /************************************************************************/
224 : /* GTIFFSetZSTDLevel() */
225 : /* Called by GTIFFBuildOverviews() to set the ZSTD level on the IFD */
226 : /* of the .ovr file. */
227 : /************************************************************************/
228 :
229 2 : void GTIFFSetZSTDLevel(GDALDatasetH hGTIFFDS, int nZSTDLevel)
230 : {
231 2 : CPLAssert(
232 : EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
233 :
234 2 : GTiffDataset *const poDS = static_cast<GTiffDataset *>(hGTIFFDS);
235 2 : poDS->m_nZSTDLevel = static_cast<signed char>(nZSTDLevel);
236 :
237 2 : poDS->ScanDirectories();
238 :
239 4 : for (int i = 0; i < poDS->m_nOverviewCount; ++i)
240 2 : poDS->m_papoOverviewDS[i]->m_nZSTDLevel = poDS->m_nZSTDLevel;
241 2 : }
242 :
243 : /************************************************************************/
244 : /* GTIFFSetMaxZError() */
245 : /* Called by GTIFFBuildOverviews() to set the Lerc max error on the IFD */
246 : /* of the .ovr file. */
247 : /************************************************************************/
248 :
249 10 : void GTIFFSetMaxZError(GDALDatasetH hGTIFFDS, double dfMaxZError)
250 : {
251 10 : CPLAssert(
252 : EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
253 :
254 10 : GTiffDataset *const poDS = static_cast<GTiffDataset *>(hGTIFFDS);
255 10 : poDS->m_dfMaxZError = dfMaxZError;
256 10 : poDS->m_dfMaxZErrorOverview = dfMaxZError;
257 :
258 10 : poDS->ScanDirectories();
259 :
260 20 : for (int i = 0; i < poDS->m_nOverviewCount; ++i)
261 : {
262 10 : poDS->m_papoOverviewDS[i]->m_dfMaxZError = poDS->m_dfMaxZError;
263 10 : poDS->m_papoOverviewDS[i]->m_dfMaxZErrorOverview =
264 10 : poDS->m_dfMaxZErrorOverview;
265 : }
266 10 : }
267 :
268 : #if HAVE_JXL
269 :
270 : /************************************************************************/
271 : /* GTIFFSetJXLLossless() */
272 : /* Called by GTIFFBuildOverviews() to set the JXL lossyness on the IFD */
273 : /* of the .ovr file. */
274 : /************************************************************************/
275 :
276 5 : void GTIFFSetJXLLossless(GDALDatasetH hGTIFFDS, bool bIsLossless)
277 : {
278 5 : CPLAssert(
279 : EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
280 :
281 5 : GTiffDataset *const poDS = static_cast<GTiffDataset *>(hGTIFFDS);
282 5 : poDS->m_bJXLLossless = bIsLossless;
283 :
284 5 : poDS->ScanDirectories();
285 :
286 5 : for (int i = 0; i < poDS->m_nOverviewCount; ++i)
287 : {
288 0 : poDS->m_papoOverviewDS[i]->m_bJXLLossless = poDS->m_bJXLLossless;
289 : }
290 5 : }
291 :
292 : /************************************************************************/
293 : /* GTIFFSetJXLEffort() */
294 : /* Called by GTIFFBuildOverviews() to set the JXL effort on the IFD */
295 : /* of the .ovr file. */
296 : /************************************************************************/
297 :
298 0 : void GTIFFSetJXLEffort(GDALDatasetH hGTIFFDS, int nEffort)
299 : {
300 0 : CPLAssert(
301 : EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
302 :
303 0 : GTiffDataset *const poDS = static_cast<GTiffDataset *>(hGTIFFDS);
304 0 : poDS->m_nJXLEffort = nEffort;
305 :
306 0 : poDS->ScanDirectories();
307 :
308 0 : for (int i = 0; i < poDS->m_nOverviewCount; ++i)
309 : {
310 0 : poDS->m_papoOverviewDS[i]->m_nJXLEffort = poDS->m_nJXLEffort;
311 : }
312 0 : }
313 :
314 : /************************************************************************/
315 : /* GTIFFSetJXLDistance() */
316 : /* Called by GTIFFBuildOverviews() to set the JXL distance on the IFD */
317 : /* of the .ovr file. */
318 : /************************************************************************/
319 :
320 1 : void GTIFFSetJXLDistance(GDALDatasetH hGTIFFDS, float fDistance)
321 : {
322 1 : CPLAssert(
323 : EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
324 :
325 1 : GTiffDataset *const poDS = static_cast<GTiffDataset *>(hGTIFFDS);
326 1 : poDS->m_fJXLDistance = fDistance;
327 :
328 1 : poDS->ScanDirectories();
329 :
330 1 : for (int i = 0; i < poDS->m_nOverviewCount; ++i)
331 : {
332 0 : poDS->m_papoOverviewDS[i]->m_fJXLDistance = poDS->m_fJXLDistance;
333 : }
334 1 : }
335 :
336 : /************************************************************************/
337 : /* GTIFFSetJXLAlphaDistance() */
338 : /* Called by GTIFFBuildOverviews() to set the JXL alpha distance on the */
339 : /* IFD of the .ovr file. */
340 : /************************************************************************/
341 :
342 1 : void GTIFFSetJXLAlphaDistance(GDALDatasetH hGTIFFDS, float fAlphaDistance)
343 : {
344 1 : CPLAssert(
345 : EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
346 :
347 1 : GTiffDataset *const poDS = static_cast<GTiffDataset *>(hGTIFFDS);
348 1 : poDS->m_fJXLAlphaDistance = fAlphaDistance;
349 :
350 1 : poDS->ScanDirectories();
351 :
352 1 : for (int i = 0; i < poDS->m_nOverviewCount; ++i)
353 : {
354 0 : poDS->m_papoOverviewDS[i]->m_fJXLAlphaDistance =
355 0 : poDS->m_fJXLAlphaDistance;
356 : }
357 1 : }
358 :
359 : #endif // HAVE_JXL
360 :
361 : /************************************************************************/
362 : /* GTiffGetAlphaValue() */
363 : /************************************************************************/
364 :
365 2630 : uint16_t GTiffGetAlphaValue(const char *pszValue, uint16_t nDefault)
366 : {
367 2630 : if (pszValue == nullptr)
368 2606 : return nDefault;
369 24 : if (EQUAL(pszValue, "YES"))
370 14 : return DEFAULT_ALPHA_TYPE;
371 10 : if (EQUAL(pszValue, "PREMULTIPLIED"))
372 5 : return EXTRASAMPLE_ASSOCALPHA;
373 5 : if (EQUAL(pszValue, "NON-PREMULTIPLIED"))
374 0 : return EXTRASAMPLE_UNASSALPHA;
375 5 : if (EQUAL(pszValue, "NO") || EQUAL(pszValue, "UNSPECIFIED"))
376 5 : return EXTRASAMPLE_UNSPECIFIED;
377 :
378 0 : return nDefault;
379 : }
380 :
381 : /************************************************************************/
382 : /* GTIFFIsStandardColorInterpretation() */
383 : /************************************************************************/
384 :
385 7903 : bool GTIFFIsStandardColorInterpretation(GDALDatasetH hSrcDS,
386 : uint16_t nPhotometric,
387 : CSLConstList papszCreationOptions)
388 : {
389 7903 : GDALDataset *poSrcDS = GDALDataset::FromHandle(hSrcDS);
390 7903 : bool bStandardColorInterp = true;
391 7903 : if (nPhotometric == PHOTOMETRIC_MINISBLACK)
392 : {
393 308673 : for (int i = 0; i < poSrcDS->GetRasterCount(); ++i)
394 : {
395 : const GDALColorInterp eInterp =
396 302496 : poSrcDS->GetRasterBand(i + 1)->GetColorInterpretation();
397 302496 : if (!(eInterp == GCI_GrayIndex || eInterp == GCI_Undefined ||
398 106 : (i > 0 && eInterp == GCI_AlphaBand)))
399 : {
400 42 : bStandardColorInterp = false;
401 42 : break;
402 : }
403 : }
404 : }
405 1684 : else if (nPhotometric == PHOTOMETRIC_PALETTE)
406 : {
407 53 : bStandardColorInterp =
408 53 : poSrcDS->GetRasterBand(1)->GetColorInterpretation() ==
409 : GCI_PaletteIndex;
410 : }
411 1631 : else if (nPhotometric == PHOTOMETRIC_RGB)
412 : {
413 1562 : int iStart = 0;
414 1562 : if (EQUAL(CSLFetchNameValueDef(papszCreationOptions, "PHOTOMETRIC", ""),
415 : "RGB"))
416 : {
417 51 : iStart = 3;
418 73 : if (poSrcDS->GetRasterCount() == 4 &&
419 22 : CSLFetchNameValue(papszCreationOptions, "ALPHA") != nullptr)
420 : {
421 5 : iStart = 4;
422 : }
423 : }
424 6211 : for (int i = iStart; i < poSrcDS->GetRasterCount(); ++i)
425 : {
426 : const GDALColorInterp eInterp =
427 4694 : poSrcDS->GetRasterBand(i + 1)->GetColorInterpretation();
428 4987 : if (!((i == 0 && eInterp == GCI_RedBand) ||
429 3227 : (i == 1 && eInterp == GCI_GreenBand) ||
430 1467 : (i == 2 && eInterp == GCI_BlueBand) ||
431 249 : (i >= 3 &&
432 204 : (eInterp == GCI_Undefined || eInterp == GCI_AlphaBand))))
433 : {
434 45 : bStandardColorInterp = false;
435 45 : break;
436 : }
437 : }
438 : }
439 130 : else if (nPhotometric == PHOTOMETRIC_YCBCR &&
440 61 : poSrcDS->GetRasterCount() == 3)
441 : {
442 : // do nothing
443 : }
444 : else
445 : {
446 8 : bStandardColorInterp = false;
447 : }
448 7903 : return bStandardColorInterp;
449 : }
450 :
451 : /************************************************************************/
452 : /* GTiffDatasetWriteRPCTag() */
453 : /* */
454 : /* Format a TAG according to: */
455 : /* */
456 : /* http://geotiff.maptools.org/rpc_prop.html */
457 : /************************************************************************/
458 :
459 12 : void GTiffDatasetWriteRPCTag(TIFF *hTIFF, char **papszRPCMD)
460 :
461 : {
462 : GDALRPCInfoV2 sRPC;
463 :
464 12 : if (!GDALExtractRPCInfoV2(papszRPCMD, &sRPC))
465 0 : return;
466 :
467 12 : double adfRPCTag[92] = {};
468 12 : adfRPCTag[0] = sRPC.dfERR_BIAS; // Error Bias
469 12 : adfRPCTag[1] = sRPC.dfERR_RAND; // Error Random
470 :
471 12 : adfRPCTag[2] = sRPC.dfLINE_OFF;
472 12 : adfRPCTag[3] = sRPC.dfSAMP_OFF;
473 12 : adfRPCTag[4] = sRPC.dfLAT_OFF;
474 12 : adfRPCTag[5] = sRPC.dfLONG_OFF;
475 12 : adfRPCTag[6] = sRPC.dfHEIGHT_OFF;
476 12 : adfRPCTag[7] = sRPC.dfLINE_SCALE;
477 12 : adfRPCTag[8] = sRPC.dfSAMP_SCALE;
478 12 : adfRPCTag[9] = sRPC.dfLAT_SCALE;
479 12 : adfRPCTag[10] = sRPC.dfLONG_SCALE;
480 12 : adfRPCTag[11] = sRPC.dfHEIGHT_SCALE;
481 :
482 12 : memcpy(adfRPCTag + 12, sRPC.adfLINE_NUM_COEFF, sizeof(double) * 20);
483 12 : memcpy(adfRPCTag + 32, sRPC.adfLINE_DEN_COEFF, sizeof(double) * 20);
484 12 : memcpy(adfRPCTag + 52, sRPC.adfSAMP_NUM_COEFF, sizeof(double) * 20);
485 12 : memcpy(adfRPCTag + 72, sRPC.adfSAMP_DEN_COEFF, sizeof(double) * 20);
486 :
487 12 : TIFFSetField(hTIFF, TIFFTAG_RPCCOEFFICIENT, 92, adfRPCTag);
488 : }
489 :
490 : /************************************************************************/
491 : /* ReadRPCTag() */
492 : /* */
493 : /* Format a TAG according to: */
494 : /* */
495 : /* http://geotiff.maptools.org/rpc_prop.html */
496 : /************************************************************************/
497 :
498 5207 : char **GTiffDatasetReadRPCTag(TIFF *hTIFF)
499 :
500 : {
501 5207 : double *padfRPCTag = nullptr;
502 : uint16_t nCount;
503 :
504 5241 : if (!TIFFGetField(hTIFF, TIFFTAG_RPCCOEFFICIENT, &nCount, &padfRPCTag) ||
505 34 : nCount != 92)
506 5172 : return nullptr;
507 :
508 34 : return gdal::tiff_common::TIFFRPCTagToRPCMetadata(padfRPCTag).StealList();
509 : }
510 :
511 : /************************************************************************/
512 : /* GTiffFormatGDALNoDataTagValue() */
513 : /************************************************************************/
514 :
515 498 : CPLString GTiffFormatGDALNoDataTagValue(double dfNoData)
516 : {
517 498 : CPLString osVal;
518 498 : if (std::isnan(dfNoData))
519 11 : osVal = "nan";
520 : else
521 487 : osVal.Printf("%.17g", dfNoData);
522 498 : return osVal;
523 : }
524 :
525 : /************************************************************************/
526 : /* GTIFFUpdatePhotometric() */
527 : /************************************************************************/
528 :
529 555 : bool GTIFFUpdatePhotometric(const char *pszPhotometric,
530 : const char *pszOptionKey, int nCompression,
531 : const char *pszInterleave, int nBands,
532 : uint16_t &nPhotometric, uint16_t &nPlanarConfig)
533 : {
534 555 : if (pszPhotometric != nullptr && pszPhotometric[0] != '\0')
535 : {
536 17 : if (EQUAL(pszPhotometric, "MINISBLACK"))
537 0 : nPhotometric = PHOTOMETRIC_MINISBLACK;
538 17 : else if (EQUAL(pszPhotometric, "MINISWHITE"))
539 0 : nPhotometric = PHOTOMETRIC_MINISWHITE;
540 17 : else if (EQUAL(pszPhotometric, "RGB"))
541 : {
542 0 : nPhotometric = PHOTOMETRIC_RGB;
543 : }
544 17 : else if (EQUAL(pszPhotometric, "CMYK"))
545 : {
546 0 : nPhotometric = PHOTOMETRIC_SEPARATED;
547 : }
548 17 : else if (EQUAL(pszPhotometric, "YCBCR"))
549 : {
550 17 : nPhotometric = PHOTOMETRIC_YCBCR;
551 :
552 : // Because of subsampling, setting YCBCR without JPEG compression
553 : // leads to a crash currently. Would need to make
554 : // GTiffRasterBand::IWriteBlock() aware of subsampling so that it
555 : // doesn't overrun buffer size returned by libtiff.
556 17 : if (nCompression != COMPRESSION_JPEG)
557 : {
558 0 : CPLError(CE_Failure, CPLE_NotSupported,
559 : "Currently, %s=YCBCR requires JPEG compression",
560 : pszOptionKey);
561 0 : return false;
562 : }
563 :
564 17 : if (pszInterleave != nullptr && pszInterleave[0] != '\0' &&
565 2 : nPlanarConfig == PLANARCONFIG_SEPARATE)
566 : {
567 0 : CPLError(CE_Failure, CPLE_NotSupported,
568 : "%s=YCBCR requires PIXEL interleaving", pszOptionKey);
569 0 : return false;
570 : }
571 : else
572 : {
573 17 : nPlanarConfig = PLANARCONFIG_CONTIG;
574 : }
575 :
576 : // YCBCR strictly requires 3 bands. Not less, not more
577 : // Issue an explicit error message as libtiff one is a bit cryptic:
578 : // JPEGLib:Bogus input colorspace.
579 17 : if (nBands != 3)
580 : {
581 0 : CPLError(CE_Failure, CPLE_NotSupported,
582 : "%s=YCBCR requires a source raster "
583 : "with only 3 bands (RGB)",
584 : pszOptionKey);
585 0 : return false;
586 : }
587 : }
588 0 : else if (EQUAL(pszPhotometric, "CIELAB"))
589 : {
590 0 : nPhotometric = PHOTOMETRIC_CIELAB;
591 : }
592 0 : else if (EQUAL(pszPhotometric, "ICCLAB"))
593 : {
594 0 : nPhotometric = PHOTOMETRIC_ICCLAB;
595 : }
596 0 : else if (EQUAL(pszPhotometric, "ITULAB"))
597 : {
598 0 : nPhotometric = PHOTOMETRIC_ITULAB;
599 : }
600 : else
601 : {
602 0 : CPLError(CE_Warning, CPLE_IllegalArg,
603 : "%s=%s value not recognised, ignoring.", pszOptionKey,
604 : pszPhotometric);
605 : }
606 : }
607 555 : return true;
608 : }
609 :
610 : /************************************************************************/
611 : /* GTiffWriteJPEGTables() */
612 : /* */
613 : /* Sets the TIFFTAG_JPEGTABLES (and TIFFTAG_REFERENCEBLACKWHITE) */
614 : /* tags immediately, instead of relying on the TIFF JPEG codec */
615 : /* to write them when it starts compressing imagery. This avoids */
616 : /* an IFD rewrite at the end of the file. */
617 : /* Must be used after having set TIFFTAG_SAMPLESPERPIXEL, */
618 : /* TIFFTAG_BITSPERSAMPLE. */
619 : /************************************************************************/
620 :
621 1073 : void GTiffWriteJPEGTables(TIFF *hTIFF, const char *pszPhotometric,
622 : const char *pszJPEGQuality,
623 : const char *pszJPEGTablesMode)
624 : {
625 : // This trick
626 : // creates a temporary in-memory file and fetches its JPEG tables so that
627 : // we can directly set them, before tif_jpeg.c compute them at the first
628 : // strip/tile writing, which is too late, since we have already crystallized
629 : // the directory. This way we avoid a directory rewriting.
630 1073 : uint16_t nBands = 0;
631 1073 : if (!TIFFGetField(hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nBands))
632 0 : nBands = 1;
633 :
634 1073 : uint16_t l_nBitsPerSample = 0;
635 1073 : if (!TIFFGetField(hTIFF, TIFFTAG_BITSPERSAMPLE, &(l_nBitsPerSample)))
636 0 : l_nBitsPerSample = 1;
637 :
638 : const CPLString osTmpFilenameIn(
639 2146 : VSIMemGenerateHiddenFilename("gtiffdataset_jpg_tmp"));
640 1073 : VSILFILE *fpTmp = nullptr;
641 2146 : CPLString osTmp;
642 1073 : char **papszLocalParameters = nullptr;
643 1073 : const int nInMemImageWidth = 16;
644 1073 : const int nInMemImageHeight = 16;
645 : papszLocalParameters =
646 1073 : CSLSetNameValue(papszLocalParameters, "COMPRESS", "JPEG");
647 : papszLocalParameters =
648 1073 : CSLSetNameValue(papszLocalParameters, "JPEG_QUALITY", pszJPEGQuality);
649 1073 : if (nBands <= 4)
650 : {
651 1073 : papszLocalParameters = CSLSetNameValue(papszLocalParameters,
652 : "PHOTOMETRIC", pszPhotometric);
653 : }
654 1073 : papszLocalParameters = CSLSetNameValue(papszLocalParameters, "BLOCKYSIZE",
655 : CPLSPrintf("%u", nInMemImageHeight));
656 1073 : papszLocalParameters = CSLSetNameValue(papszLocalParameters, "NBITS",
657 : CPLSPrintf("%u", l_nBitsPerSample));
658 1073 : papszLocalParameters = CSLSetNameValue(papszLocalParameters,
659 : "JPEGTABLESMODE", pszJPEGTablesMode);
660 : papszLocalParameters =
661 1073 : CSLSetNameValue(papszLocalParameters, "WRITE_JPEGTABLE_TAG", "NO");
662 :
663 : bool bTileInterleaving;
664 : TIFF *hTIFFTmp =
665 2146 : GTiffDataset::CreateLL(osTmpFilenameIn, nInMemImageWidth,
666 1073 : nInMemImageHeight, (nBands <= 4) ? nBands : 1,
667 1073 : (l_nBitsPerSample <= 8) ? GDT_Byte : GDT_UInt16,
668 : 0.0, 0, papszLocalParameters, &fpTmp, osTmp,
669 : /* bCreateCopy=*/false, bTileInterleaving);
670 1073 : CSLDestroy(papszLocalParameters);
671 1073 : if (hTIFFTmp)
672 : {
673 1073 : uint16_t l_nPhotometric = 0;
674 1073 : int nJpegTablesModeIn = 0;
675 1073 : TIFFGetField(hTIFFTmp, TIFFTAG_PHOTOMETRIC, &(l_nPhotometric));
676 1073 : TIFFGetField(hTIFFTmp, TIFFTAG_JPEGTABLESMODE, &nJpegTablesModeIn);
677 1073 : TIFFWriteCheck(hTIFFTmp, FALSE, "CreateLL");
678 1073 : TIFFWriteDirectory(hTIFFTmp);
679 1073 : TIFFSetDirectory(hTIFFTmp, 0);
680 : // Now, reset quality and jpegcolormode.
681 1073 : const int l_nJpegQuality = pszJPEGQuality ? atoi(pszJPEGQuality) : 0;
682 1073 : if (l_nJpegQuality > 0)
683 967 : TIFFSetField(hTIFFTmp, TIFFTAG_JPEGQUALITY, l_nJpegQuality);
684 1461 : if (l_nPhotometric == PHOTOMETRIC_YCBCR &&
685 388 : CPLTestBool(CPLGetConfigOption("CONVERT_YCBCR_TO_RGB", "YES")))
686 : {
687 388 : TIFFSetField(hTIFFTmp, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
688 : }
689 1073 : if (nJpegTablesModeIn >= 0)
690 1069 : TIFFSetField(hTIFFTmp, TIFFTAG_JPEGTABLESMODE, nJpegTablesModeIn);
691 :
692 1073 : GPtrDiff_t nBlockSize = static_cast<GPtrDiff_t>(nInMemImageWidth) *
693 : nInMemImageHeight *
694 1073 : ((nBands <= 4) ? nBands : 1);
695 1073 : if (l_nBitsPerSample == 12)
696 590 : nBlockSize = (nBlockSize * 3) / 2;
697 1073 : std::vector<GByte> abyZeroData(nBlockSize, 0);
698 1073 : TIFFWriteEncodedStrip(hTIFFTmp, 0, &abyZeroData[0], nBlockSize);
699 :
700 1073 : uint32_t nJPEGTableSize = 0;
701 1073 : void *pJPEGTable = nullptr;
702 1073 : if (TIFFGetField(hTIFFTmp, TIFFTAG_JPEGTABLES, &nJPEGTableSize,
703 1073 : &pJPEGTable))
704 1070 : TIFFSetField(hTIFF, TIFFTAG_JPEGTABLES, nJPEGTableSize, pJPEGTable);
705 :
706 1073 : float *ref = nullptr;
707 1073 : if (TIFFGetField(hTIFFTmp, TIFFTAG_REFERENCEBLACKWHITE, &ref))
708 388 : TIFFSetField(hTIFF, TIFFTAG_REFERENCEBLACKWHITE, ref);
709 :
710 1073 : XTIFFClose(hTIFFTmp);
711 1073 : CPL_IGNORE_RET_VAL(VSIFCloseL(fpTmp));
712 : }
713 1073 : VSIUnlink(osTmpFilenameIn);
714 1073 : }
715 :
716 : #if !defined(SUPPORTS_LIBTIFF_OPEN_OPTIONS)
717 :
718 : /************************************************************************/
719 : /* GTiffWarningHandler() */
720 : /************************************************************************/
721 : static void GTiffWarningHandler(const char *module, const char *fmt, va_list ap)
722 : {
723 : if (GTIFFGetThreadLocalLibtiffError() > 0)
724 : {
725 : GTIFFGetThreadLocalLibtiffError()++;
726 : if (GTIFFGetThreadLocalLibtiffError() > 10)
727 : return;
728 : }
729 :
730 : if (strstr(fmt, "nknown field") != nullptr)
731 : return;
732 :
733 : char *pszModFmt = gdal::tiff_common::PrepareTIFFErrorFormat(module, fmt);
734 : if (strstr(fmt, "does not end in null byte") != nullptr)
735 : {
736 : CPLString osMsg;
737 : osMsg.vPrintf(pszModFmt, ap);
738 : CPLDebug("GTiff", "%s", osMsg.c_str());
739 : }
740 : else
741 : {
742 : CPLErrorV(CE_Warning, CPLE_AppDefined, pszModFmt, ap);
743 : }
744 : CPLFree(pszModFmt);
745 : return;
746 : }
747 :
748 : /************************************************************************/
749 : /* GTiffErrorHandler() */
750 : /************************************************************************/
751 : static void GTiffErrorHandler(const char *module, const char *fmt, va_list ap)
752 : {
753 : if (GTIFFGetThreadLocalLibtiffError() > 0)
754 : {
755 : GTIFFGetThreadLocalLibtiffError()++;
756 : if (GTIFFGetThreadLocalLibtiffError() > 10)
757 : return;
758 : }
759 :
760 : if (strcmp(fmt, "Maximum TIFF file size exceeded") == 0)
761 : {
762 : if (bThreadLocalInExternalOvr)
763 : fmt = "Maximum TIFF file size exceeded. "
764 : "Use --config BIGTIFF_OVERVIEW YES configuration option.";
765 : else
766 : fmt = "Maximum TIFF file size exceeded. "
767 : "Use BIGTIFF=YES creation option.";
768 : }
769 :
770 : char *pszModFmt = gdal::tiff_common::PrepareTIFFErrorFormat(module, fmt);
771 : CPLErrorV(CE_Failure, CPLE_AppDefined, pszModFmt, ap);
772 : CPLFree(pszModFmt);
773 : return;
774 : }
775 : #else
776 :
777 : /************************************************************************/
778 : /* GTiffWarningHandlerExt() */
779 : /************************************************************************/
780 : extern int GTiffWarningHandlerExt(TIFF *tif, void *user_data,
781 : const char *module, const char *fmt,
782 : va_list ap);
783 :
784 327 : int GTiffWarningHandlerExt(TIFF *tif, void *user_data, const char *module,
785 : const char *fmt, va_list ap)
786 : {
787 : (void)tif;
788 : (void)user_data;
789 327 : auto &nLibtiffErrors = GTIFFGetThreadLocalLibtiffError();
790 : // cppcheck-suppress knownConditionTrueFalse
791 327 : if (nLibtiffErrors > 0)
792 : {
793 217 : nLibtiffErrors++;
794 : // cppcheck-suppress knownConditionTrueFalse
795 217 : if (nLibtiffErrors > 10)
796 0 : return 1;
797 : }
798 :
799 327 : if (strstr(fmt, "nknown field") != nullptr)
800 0 : return 1;
801 :
802 327 : char *pszModFmt = gdal::tiff_common::PrepareTIFFErrorFormat(module, fmt);
803 327 : if (strstr(fmt, "does not end in null byte") != nullptr)
804 : {
805 2 : CPLString osMsg;
806 1 : osMsg.vPrintf(pszModFmt, ap);
807 1 : CPLDebug("GTiff", "%s", osMsg.c_str());
808 : }
809 : else
810 : {
811 326 : CPLErrorV(CE_Warning, CPLE_AppDefined, pszModFmt, ap);
812 : }
813 327 : CPLFree(pszModFmt);
814 327 : return 1;
815 : }
816 :
817 : /************************************************************************/
818 : /* GTiffErrorHandlerExt() */
819 : /************************************************************************/
820 : extern int GTiffErrorHandlerExt(TIFF *tif, void *user_data, const char *module,
821 : const char *fmt, va_list ap);
822 :
823 248 : int GTiffErrorHandlerExt(TIFF *tif, void *user_data, const char *module,
824 : const char *fmt, va_list ap)
825 : {
826 : (void)tif;
827 : (void)user_data;
828 248 : auto &nLibtiffErrors = GTIFFGetThreadLocalLibtiffError();
829 : // cppcheck-suppress knownConditionTrueFalse
830 248 : if (nLibtiffErrors > 0)
831 : {
832 110 : nLibtiffErrors++;
833 : // cppcheck-suppress knownConditionTrueFalse
834 110 : if (nLibtiffErrors > 10)
835 0 : return 1;
836 : }
837 :
838 248 : if (strcmp(fmt, "Maximum TIFF file size exceeded") == 0)
839 : {
840 0 : if (bThreadLocalInExternalOvr)
841 0 : fmt = "Maximum TIFF file size exceeded. "
842 : "Use --config BIGTIFF_OVERVIEW YES configuration option.";
843 : else
844 0 : fmt = "Maximum TIFF file size exceeded. "
845 : "Use BIGTIFF=YES creation option.";
846 : }
847 :
848 248 : char *pszModFmt = gdal::tiff_common::PrepareTIFFErrorFormat(module, fmt);
849 248 : CPLErrorV(CE_Failure, CPLE_AppDefined, pszModFmt, ap);
850 248 : CPLFree(pszModFmt);
851 248 : return 1;
852 : }
853 :
854 : #endif
855 :
856 : /************************************************************************/
857 : /* GTiffTagExtender() */
858 : /* */
859 : /* Install tags specially known to GDAL. */
860 : /************************************************************************/
861 :
862 : static TIFFExtendProc _ParentExtender = nullptr;
863 :
864 133749 : static void GTiffTagExtender(TIFF *tif)
865 :
866 : {
867 133749 : const TIFFFieldInfo xtiffFieldInfo[] = {
868 : {TIFFTAG_GDAL_METADATA, -1, -1, TIFF_ASCII, FIELD_CUSTOM, TRUE, FALSE,
869 : const_cast<char *>("GDALMetadata")},
870 : {TIFFTAG_GDAL_NODATA, -1, -1, TIFF_ASCII, FIELD_CUSTOM, TRUE, FALSE,
871 : const_cast<char *>("GDALNoDataValue")},
872 : {TIFFTAG_RPCCOEFFICIENT, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE,
873 : const_cast<char *>("RPCCoefficient")},
874 : {TIFFTAG_TIFF_RSID, -1, -1, TIFF_ASCII, FIELD_CUSTOM, TRUE, FALSE,
875 : const_cast<char *>("TIFF_RSID")},
876 : {TIFFTAG_GEO_METADATA, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_BYTE,
877 : FIELD_CUSTOM, TRUE, TRUE, const_cast<char *>("GEO_METADATA")}};
878 :
879 133749 : if (_ParentExtender)
880 0 : (*_ParentExtender)(tif);
881 :
882 133749 : TIFFMergeFieldInfo(tif, xtiffFieldInfo,
883 : sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]));
884 133770 : }
885 :
886 : /************************************************************************/
887 : /* GTiffOneTimeInit() */
888 : /* */
889 : /* This is stuff that is initialized for the TIFF library just */
890 : /* once. We deliberately defer the initialization till the */
891 : /* first time we are likely to call into libtiff to avoid */
892 : /* unnecessary paging in of the library for GDAL apps that */
893 : /* don't use it. */
894 : /************************************************************************/
895 :
896 : static std::mutex oDeleteMutex;
897 : #ifdef HAVE_JXL
898 : static TIFFCodec *pJXLCodec = nullptr;
899 : static TIFFCodec *pJXLCodecDNG17 = nullptr;
900 : #endif
901 :
902 34057 : void GTiffOneTimeInit()
903 :
904 : {
905 34057 : std::lock_guard<std::mutex> oLock(oDeleteMutex);
906 :
907 : static bool bOneTimeInitDone = false;
908 34095 : if (bOneTimeInitDone)
909 33424 : return;
910 :
911 671 : bOneTimeInitDone = true;
912 :
913 : #ifdef HAVE_JXL
914 671 : if (pJXLCodec == nullptr)
915 : {
916 671 : pJXLCodec = TIFFRegisterCODEC(COMPRESSION_JXL, "JXL", TIFFInitJXL);
917 671 : pJXLCodecDNG17 =
918 671 : TIFFRegisterCODEC(COMPRESSION_JXL_DNG_1_7, "JXL", TIFFInitJXL);
919 : }
920 : #endif
921 :
922 671 : _ParentExtender = TIFFSetTagExtender(GTiffTagExtender);
923 :
924 : #if !defined(SUPPORTS_LIBTIFF_OPEN_OPTIONS)
925 : TIFFSetWarningHandler(GTiffWarningHandler);
926 : TIFFSetErrorHandler(GTiffErrorHandler);
927 : #endif
928 :
929 671 : LibgeotiffOneTimeInit();
930 : }
931 :
932 : /************************************************************************/
933 : /* GDALDeregister_GTiff() */
934 : /************************************************************************/
935 :
936 1122 : static void GDALDeregister_GTiff(GDALDriver *)
937 :
938 : {
939 : #ifdef HAVE_JXL
940 1122 : if (pJXLCodec)
941 434 : TIFFUnRegisterCODEC(pJXLCodec);
942 1122 : pJXLCodec = nullptr;
943 1122 : if (pJXLCodecDNG17)
944 434 : TIFFUnRegisterCODEC(pJXLCodecDNG17);
945 1122 : pJXLCodecDNG17 = nullptr;
946 : #endif
947 1122 : }
948 :
949 : #define COMPRESSION_ENTRY(x, bWriteSupported) \
950 : { \
951 : COMPRESSION_##x, STRINGIFY(x), bWriteSupported \
952 : }
953 :
954 : static const struct
955 : {
956 : int nCode;
957 : const char *pszText;
958 : bool bWriteSupported;
959 : } asCompressionNames[] = {
960 : // Compression methods in read/write mode
961 : COMPRESSION_ENTRY(NONE, true),
962 : COMPRESSION_ENTRY(CCITTRLE, true),
963 : COMPRESSION_ENTRY(CCITTFAX3, true),
964 : {COMPRESSION_CCITTFAX3, "FAX3", true}, // alternate name for write side
965 : COMPRESSION_ENTRY(CCITTFAX4, true),
966 : {COMPRESSION_CCITTFAX4, "FAX4", true}, // alternate name for write side
967 : COMPRESSION_ENTRY(LZW, true),
968 : COMPRESSION_ENTRY(JPEG, true),
969 : COMPRESSION_ENTRY(PACKBITS, true),
970 : {COMPRESSION_ADOBE_DEFLATE, "DEFLATE",
971 : true}, // manual entry since we want the user friendly name to be DEFLATE
972 : {COMPRESSION_ADOBE_DEFLATE, "ZIP", true}, // alternate name for write side
973 : COMPRESSION_ENTRY(LZMA, true),
974 : COMPRESSION_ENTRY(ZSTD, true),
975 : COMPRESSION_ENTRY(LERC, true),
976 : {COMPRESSION_LERC, "LERC_DEFLATE", true},
977 : {COMPRESSION_LERC, "LERC_ZSTD", true},
978 : COMPRESSION_ENTRY(WEBP, true),
979 : // COMPRESSION_JXL_DNG_1_7 must be *before* COMPRESSION_JXL
980 : {COMPRESSION_JXL_DNG_1_7, "JXL", true},
981 : {COMPRESSION_JXL, "JXL",
982 : true}, // deprecated. No longer used for writing since GDAL 3.11
983 :
984 : // Compression methods in read-only
985 : COMPRESSION_ENTRY(OJPEG, false),
986 : COMPRESSION_ENTRY(NEXT, false),
987 : COMPRESSION_ENTRY(CCITTRLEW, false),
988 : COMPRESSION_ENTRY(THUNDERSCAN, false),
989 : COMPRESSION_ENTRY(PIXARFILM, false),
990 : COMPRESSION_ENTRY(PIXARLOG, false),
991 : COMPRESSION_ENTRY(DEFLATE, false), // COMPRESSION_DEFLATE is deprecated
992 : COMPRESSION_ENTRY(DCS, false),
993 : COMPRESSION_ENTRY(JBIG, false),
994 : COMPRESSION_ENTRY(SGILOG, false),
995 : COMPRESSION_ENTRY(SGILOG24, false),
996 : COMPRESSION_ENTRY(JP2000, false),
997 : };
998 :
999 : /************************************************************************/
1000 : /* GTIFFGetCompressionMethodName() */
1001 : /************************************************************************/
1002 :
1003 3756 : const char *GTIFFGetCompressionMethodName(int nCompressionCode)
1004 : {
1005 44582 : for (const auto &entry : asCompressionNames)
1006 : {
1007 44580 : if (entry.nCode == nCompressionCode)
1008 : {
1009 3754 : return entry.pszText;
1010 : }
1011 : }
1012 2 : return nullptr;
1013 : }
1014 :
1015 : /************************************************************************/
1016 : /* GTIFFGetCompressionMethod() */
1017 : /************************************************************************/
1018 :
1019 3412 : int GTIFFGetCompressionMethod(const char *pszValue, const char *pszVariableName)
1020 : {
1021 3412 : int nCompression = COMPRESSION_NONE;
1022 3412 : bool bFoundMatch = false;
1023 29811 : for (const auto &entry : asCompressionNames)
1024 : {
1025 29809 : if (entry.bWriteSupported && EQUAL(entry.pszText, pszValue))
1026 : {
1027 3410 : bFoundMatch = true;
1028 3410 : nCompression = entry.nCode;
1029 3410 : break;
1030 : }
1031 : }
1032 :
1033 3412 : if (!bFoundMatch)
1034 : {
1035 2 : CPLError(CE_Warning, CPLE_IllegalArg,
1036 : "%s=%s value not recognised, ignoring.", pszVariableName,
1037 : pszValue);
1038 : }
1039 :
1040 6819 : if (nCompression != COMPRESSION_NONE &&
1041 3408 : !TIFFIsCODECConfigured(static_cast<uint16_t>(nCompression)))
1042 : {
1043 0 : CPLError(CE_Failure, CPLE_AppDefined,
1044 : "Cannot create TIFF file due to missing codec for %s.",
1045 : pszValue);
1046 0 : return -1;
1047 : }
1048 :
1049 3411 : return nCompression;
1050 : }
1051 :
1052 : /************************************************************************/
1053 : /* GTiffGetCompressValues() */
1054 : /************************************************************************/
1055 :
1056 3482 : CPLString GTiffGetCompressValues(bool &bHasLZW, bool &bHasDEFLATE,
1057 : bool &bHasLZMA, bool &bHasZSTD, bool &bHasJPEG,
1058 : bool &bHasWebP, bool &bHasLERC, bool bForCOG)
1059 : {
1060 3482 : bHasLZW = false;
1061 3482 : bHasDEFLATE = false;
1062 3482 : bHasLZMA = false;
1063 3482 : bHasZSTD = false;
1064 3482 : bHasJPEG = false;
1065 3482 : bHasWebP = false;
1066 3482 : bHasLERC = false;
1067 :
1068 : /* -------------------------------------------------------------------- */
1069 : /* Determine which compression codecs are available that we */
1070 : /* want to advertise. If we are using an old libtiff we won't */
1071 : /* be able to find out so we just assume all are available. */
1072 : /* -------------------------------------------------------------------- */
1073 3482 : CPLString osCompressValues = " <Value>NONE</Value>";
1074 :
1075 3482 : TIFFCodec *codecs = TIFFGetConfiguredCODECs();
1076 :
1077 73122 : for (TIFFCodec *c = codecs; c->name; ++c)
1078 : {
1079 69640 : if (c->scheme == COMPRESSION_PACKBITS && !bForCOG)
1080 : {
1081 1741 : osCompressValues += " <Value>PACKBITS</Value>";
1082 : }
1083 67899 : else if (c->scheme == COMPRESSION_JPEG)
1084 : {
1085 3482 : bHasJPEG = true;
1086 3482 : osCompressValues += " <Value>JPEG</Value>";
1087 : }
1088 64417 : else if (c->scheme == COMPRESSION_LZW)
1089 : {
1090 3482 : bHasLZW = true;
1091 3482 : osCompressValues += " <Value>LZW</Value>";
1092 : }
1093 60935 : else if (c->scheme == COMPRESSION_ADOBE_DEFLATE)
1094 : {
1095 3482 : bHasDEFLATE = true;
1096 3482 : osCompressValues += " <Value>DEFLATE</Value>";
1097 : }
1098 57453 : else if (c->scheme == COMPRESSION_CCITTRLE && !bForCOG)
1099 : {
1100 1741 : osCompressValues += " <Value>CCITTRLE</Value>";
1101 : }
1102 55712 : else if (c->scheme == COMPRESSION_CCITTFAX3 && !bForCOG)
1103 : {
1104 1741 : osCompressValues += " <Value>CCITTFAX3</Value>";
1105 : }
1106 53971 : else if (c->scheme == COMPRESSION_CCITTFAX4 && !bForCOG)
1107 : {
1108 1741 : osCompressValues += " <Value>CCITTFAX4</Value>";
1109 : }
1110 52230 : else if (c->scheme == COMPRESSION_LZMA)
1111 : {
1112 3482 : bHasLZMA = true;
1113 3482 : osCompressValues += " <Value>LZMA</Value>";
1114 : }
1115 48748 : else if (c->scheme == COMPRESSION_ZSTD)
1116 : {
1117 3482 : bHasZSTD = true;
1118 3482 : osCompressValues += " <Value>ZSTD</Value>";
1119 : }
1120 45266 : else if (c->scheme == COMPRESSION_WEBP)
1121 : {
1122 3482 : bHasWebP = true;
1123 3482 : osCompressValues += " <Value>WEBP</Value>";
1124 : }
1125 41784 : else if (c->scheme == COMPRESSION_LERC)
1126 : {
1127 3482 : bHasLERC = true;
1128 : }
1129 : }
1130 3482 : if (bHasLERC)
1131 : {
1132 : osCompressValues += " <Value>LERC</Value>"
1133 3482 : " <Value>LERC_DEFLATE</Value>";
1134 3482 : if (bHasZSTD)
1135 : {
1136 3482 : osCompressValues += " <Value>LERC_ZSTD</Value>";
1137 : }
1138 : }
1139 : #ifdef HAVE_JXL
1140 3482 : osCompressValues += " <Value>JXL</Value>";
1141 : #endif
1142 3482 : _TIFFfree(codecs);
1143 :
1144 3482 : return osCompressValues;
1145 : }
1146 :
1147 : /************************************************************************/
1148 : /* OGRGTiffDriverGetSubdatasetInfo() */
1149 : /************************************************************************/
1150 :
1151 : struct GTiffDriverSubdatasetInfo final : public GDALSubdatasetInfo
1152 : {
1153 : public:
1154 7 : explicit GTiffDriverSubdatasetInfo(const std::string &fileName)
1155 7 : : GDALSubdatasetInfo(fileName)
1156 : {
1157 7 : }
1158 :
1159 : // GDALSubdatasetInfo interface
1160 : private:
1161 : void parseFileName() override;
1162 : };
1163 :
1164 7 : void GTiffDriverSubdatasetInfo::parseFileName()
1165 : {
1166 7 : if (!STARTS_WITH_CI(m_fileName.c_str(), "GTIFF_DIR:"))
1167 : {
1168 0 : return;
1169 : }
1170 :
1171 7 : CPLStringList aosParts{CSLTokenizeString2(m_fileName.c_str(), ":", 0)};
1172 7 : const int iPartsCount{CSLCount(aosParts)};
1173 :
1174 7 : if (iPartsCount == 3 || iPartsCount == 4)
1175 : {
1176 :
1177 7 : m_driverPrefixComponent = aosParts[0];
1178 :
1179 : const bool hasDriveLetter{
1180 9 : strlen(aosParts[2]) == 1 &&
1181 2 : std::isalpha(static_cast<unsigned char>(aosParts[2][0]))};
1182 :
1183 : // Check for drive letter
1184 7 : if (iPartsCount == 4)
1185 : {
1186 : // Invalid
1187 2 : if (!hasDriveLetter)
1188 : {
1189 0 : return;
1190 : }
1191 2 : m_pathComponent = aosParts[2];
1192 2 : m_pathComponent.append(":");
1193 2 : m_pathComponent.append(aosParts[3]);
1194 : }
1195 : else // count is 3
1196 : {
1197 5 : if (hasDriveLetter)
1198 : {
1199 0 : return;
1200 : }
1201 5 : m_pathComponent = aosParts[2];
1202 : }
1203 :
1204 7 : m_subdatasetComponent = aosParts[1];
1205 : }
1206 : }
1207 :
1208 2787 : static GDALSubdatasetInfo *GTiffDriverGetSubdatasetInfo(const char *pszFileName)
1209 : {
1210 2787 : if (STARTS_WITH_CI(pszFileName, "GTIFF_DIR:"))
1211 : {
1212 : std::unique_ptr<GDALSubdatasetInfo> info =
1213 7 : std::make_unique<GTiffDriverSubdatasetInfo>(pszFileName);
1214 21 : if (!info->GetSubdatasetComponent().empty() &&
1215 14 : !info->GetPathComponent().empty())
1216 : {
1217 7 : return info.release();
1218 : }
1219 : }
1220 2780 : return nullptr;
1221 : }
1222 :
1223 : /************************************************************************/
1224 : /* GDALRegister_GTiff() */
1225 : /************************************************************************/
1226 :
1227 2024 : void GDALRegister_GTiff()
1228 :
1229 : {
1230 2024 : if (GDALGetDriverByName("GTiff") != nullptr)
1231 283 : return;
1232 :
1233 3482 : CPLString osOptions;
1234 :
1235 1741 : bool bHasLZW = false;
1236 1741 : bool bHasDEFLATE = false;
1237 1741 : bool bHasLZMA = false;
1238 1741 : bool bHasZSTD = false;
1239 1741 : bool bHasJPEG = false;
1240 1741 : bool bHasWebP = false;
1241 1741 : bool bHasLERC = false;
1242 : CPLString osCompressValues(GTiffGetCompressValues(
1243 : bHasLZW, bHasDEFLATE, bHasLZMA, bHasZSTD, bHasJPEG, bHasWebP, bHasLERC,
1244 3482 : false /* bForCOG */));
1245 :
1246 1741 : GDALDriver *poDriver = new GDALDriver();
1247 :
1248 : /* -------------------------------------------------------------------- */
1249 : /* Build full creation option list. */
1250 : /* -------------------------------------------------------------------- */
1251 : osOptions = "<CreationOptionList>"
1252 1741 : " <Option name='COMPRESS' type='string-select'>";
1253 1741 : osOptions += osCompressValues;
1254 1741 : osOptions += " </Option>";
1255 1741 : if (bHasLZW || bHasDEFLATE || bHasZSTD)
1256 : osOptions += ""
1257 : " <Option name='PREDICTOR' type='int' "
1258 : "description='Predictor Type (1=default, 2=horizontal "
1259 : "differencing, 3=floating point prediction)' "
1260 1741 : "default='1'/>";
1261 : osOptions +=
1262 : ""
1263 : " <Option name='DISCARD_LSB' type='string' description='Number of "
1264 : "least-significant bits to set to clear as a single value or "
1265 1741 : "comma-separated list of values for per-band values'/>";
1266 1741 : if (bHasJPEG)
1267 : {
1268 : osOptions +=
1269 : ""
1270 : " <Option name='JPEG_QUALITY' type='int' description='JPEG "
1271 : "quality 1-100' min='1' max='100' default='75'/>"
1272 : " <Option name='JPEGTABLESMODE' type='int' description='Content "
1273 : "of JPEGTABLES tag. 0=no JPEGTABLES tag, 1=Quantization tables "
1274 1741 : "only, 2=Huffman tables only, 3=Both' default='1'/>";
1275 : #ifdef JPEG_DIRECT_COPY
1276 : osOptions +=
1277 : ""
1278 : " <Option name='JPEG_DIRECT_COPY' type='boolean' description='To "
1279 : "copy without any decompression/recompression a JPEG source file' "
1280 : "default='NO'/>";
1281 : #endif
1282 : }
1283 1741 : if (bHasDEFLATE)
1284 : {
1285 : #ifdef LIBDEFLATE_SUPPORT
1286 : osOptions += ""
1287 : " <Option name='ZLEVEL' type='int' description='DEFLATE "
1288 1741 : "compression level 1-12' min='1' max='12' default='6'/>";
1289 : #else
1290 : osOptions += ""
1291 : " <Option name='ZLEVEL' type='int' description='DEFLATE "
1292 : "compression level 1-9' min='1' max='9' default='6'/>";
1293 : #endif
1294 : }
1295 1741 : if (bHasLZMA)
1296 : osOptions +=
1297 : ""
1298 : " <Option name='LZMA_PRESET' type='int' description='LZMA "
1299 1741 : "compression level 0(fast)-9(slow)' min='0' max='9' default='6'/>";
1300 1741 : if (bHasZSTD)
1301 : osOptions +=
1302 : ""
1303 : " <Option name='ZSTD_LEVEL' type='int' description='ZSTD "
1304 : "compression level 1(fast)-22(slow)' min='1' max='22' "
1305 1741 : "default='9'/>";
1306 1741 : if (bHasLERC)
1307 : {
1308 : osOptions +=
1309 : ""
1310 : " <Option name='MAX_Z_ERROR' type='float' description='Maximum "
1311 : "error for LERC compression' default='0'/>"
1312 : " <Option name='MAX_Z_ERROR_OVERVIEW' type='float' "
1313 : "description='Maximum error for LERC compression in overviews' "
1314 1741 : "default='0'/>";
1315 : }
1316 1741 : if (bHasWebP)
1317 : {
1318 : #ifndef DEFAULT_WEBP_LEVEL
1319 : #error "DEFAULT_WEBP_LEVEL should be defined"
1320 : #endif
1321 : osOptions +=
1322 : ""
1323 : #if WEBP_ENCODER_ABI_VERSION >= 0x0100
1324 : " <Option name='WEBP_LOSSLESS' type='boolean' "
1325 : "description='Whether lossless compression should be used' "
1326 : "default='FALSE'/>"
1327 : #endif
1328 : " <Option name='WEBP_LEVEL' type='int' description='WEBP quality "
1329 : "level. Low values result in higher compression ratios' "
1330 1741 : "default='" XSTRINGIFY(DEFAULT_WEBP_LEVEL) "'/>";
1331 : }
1332 : #ifdef HAVE_JXL
1333 : osOptions +=
1334 : ""
1335 : " <Option name='JXL_LOSSLESS' type='boolean' description='Whether "
1336 : "JPEGXL compression should be lossless' default='YES'/>"
1337 : " <Option name='JXL_EFFORT' type='int' description='Level of effort "
1338 : "1(fast)-9(slow)' min='1' max='9' default='5'/>"
1339 : " <Option name='JXL_DISTANCE' type='float' description='Distance "
1340 : "level for lossy compression (0=mathematically lossless, 1.0=visually "
1341 1741 : "lossless, usual range [0.5,3])' default='1.0' min='0.01' max='25.0'/>";
1342 : #ifdef HAVE_JxlEncoderSetExtraChannelDistance
1343 : osOptions += " <Option name='JXL_ALPHA_DISTANCE' type='float' "
1344 : "description='Distance level for alpha channel "
1345 : "(-1=same as non-alpha channels, "
1346 : "0=mathematically lossless, 1.0=visually lossless, "
1347 1741 : "usual range [0.5,3])' default='-1' min='-1' max='25.0'/>";
1348 : #endif
1349 : #endif
1350 : osOptions +=
1351 : ""
1352 : " <Option name='NUM_THREADS' type='string' description='Number of "
1353 : "worker threads for compression. Can be set to ALL_CPUS' default='1'/>"
1354 : " <Option name='NBITS' type='int' description='BITS for sub-byte "
1355 : "files (1-7), sub-uint16_t (9-15), sub-uint32_t (17-31), or float32 "
1356 : "(16)'/>"
1357 : " <Option name='INTERLEAVE' type='string-select' default='PIXEL'>"
1358 : " <Value>BAND</Value>"
1359 : " <Value>PIXEL</Value>"
1360 : " </Option>"
1361 : " <Option name='TILED' type='boolean' description='Switch to tiled "
1362 : "format' default='NO'/>"
1363 : " <Option name='TFW' type='boolean' description='Write out world "
1364 : "file'/>"
1365 : " <Option name='RPB' type='boolean' description='Write out .RPB "
1366 : "(RPC) file'/>"
1367 : " <Option name='RPCTXT' type='boolean' description='Write out "
1368 : "_RPC.TXT file'/>"
1369 : " <Option name='BLOCKXSIZE' type='int' description='Tile Width' "
1370 : "default='256'/>"
1371 : " <Option name='BLOCKYSIZE' type='int' description='Tile/Strip "
1372 : "Height'/>"
1373 : " <Option name='PHOTOMETRIC' type='string-select'>"
1374 : " <Value>MINISBLACK</Value>"
1375 : " <Value>MINISWHITE</Value>"
1376 : " <Value>PALETTE</Value>"
1377 : " <Value>RGB</Value>"
1378 : " <Value>CMYK</Value>"
1379 : " <Value>YCBCR</Value>"
1380 : " <Value>CIELAB</Value>"
1381 : " <Value>ICCLAB</Value>"
1382 : " <Value>ITULAB</Value>"
1383 : " </Option>"
1384 : " <Option name='SPARSE_OK' type='boolean' description='Should empty "
1385 : "blocks be omitted on disk?' default='FALSE'/>"
1386 : " <Option name='ALPHA' type='string-select' description='Mark first "
1387 : "extrasample as being alpha'>"
1388 : " <Value>NON-PREMULTIPLIED</Value>"
1389 : " <Value>PREMULTIPLIED</Value>"
1390 : " <Value>UNSPECIFIED</Value>"
1391 : " <Value aliasOf='NON-PREMULTIPLIED'>YES</Value>"
1392 : " <Value aliasOf='UNSPECIFIED'>NO</Value>"
1393 : " </Option>"
1394 : " <Option name='PROFILE' type='string-select' default='GDALGeoTIFF'>"
1395 : " <Value>GDALGeoTIFF</Value>"
1396 : " <Value>GeoTIFF</Value>"
1397 : " <Value>BASELINE</Value>"
1398 : " </Option>"
1399 : " <Option name='PIXELTYPE' type='string-select' "
1400 : "description='(deprecated, use Int8 datatype)'>"
1401 : " <Value>DEFAULT</Value>"
1402 : " <Value>SIGNEDBYTE</Value>"
1403 : " </Option>"
1404 : " <Option name='BIGTIFF' type='string-select' description='Force "
1405 : "creation of BigTIFF file' default='IF_NEEDED'>"
1406 : " <Value>YES</Value>"
1407 : " <Value>NO</Value>"
1408 : " <Value>IF_NEEDED</Value>"
1409 : " <Value>IF_SAFER</Value>"
1410 : " </Option>"
1411 : " <Option name='ENDIANNESS' type='string-select' default='NATIVE' "
1412 : "description='Force endianness of created file. For DEBUG purpose "
1413 : "mostly'>"
1414 : " <Value>NATIVE</Value>"
1415 : " <Value>INVERTED</Value>"
1416 : " <Value>LITTLE</Value>"
1417 : " <Value>BIG</Value>"
1418 : " </Option>"
1419 : " <Option name='COPY_SRC_OVERVIEWS' type='boolean' default='NO' "
1420 : "description='Force copy of overviews of source dataset "
1421 : "(CreateCopy())'/>"
1422 : " <Option name='SOURCE_ICC_PROFILE' type='string' description='ICC "
1423 : "profile'/>"
1424 : " <Option name='SOURCE_PRIMARIES_RED' type='string' "
1425 : "description='x,y,1.0 (xyY) red chromaticity'/>"
1426 : " <Option name='SOURCE_PRIMARIES_GREEN' type='string' "
1427 : "description='x,y,1.0 (xyY) green chromaticity'/>"
1428 : " <Option name='SOURCE_PRIMARIES_BLUE' type='string' "
1429 : "description='x,y,1.0 (xyY) blue chromaticity'/>"
1430 : " <Option name='SOURCE_WHITEPOINT' type='string' "
1431 : "description='x,y,1.0 (xyY) whitepoint'/>"
1432 : " <Option name='TIFFTAG_TRANSFERFUNCTION_RED' type='string' "
1433 : "description='Transfer function for red'/>"
1434 : " <Option name='TIFFTAG_TRANSFERFUNCTION_GREEN' type='string' "
1435 : "description='Transfer function for green'/>"
1436 : " <Option name='TIFFTAG_TRANSFERFUNCTION_BLUE' type='string' "
1437 : "description='Transfer function for blue'/>"
1438 : " <Option name='TIFFTAG_TRANSFERRANGE_BLACK' type='string' "
1439 : "description='Transfer range for black'/>"
1440 : " <Option name='TIFFTAG_TRANSFERRANGE_WHITE' type='string' "
1441 : "description='Transfer range for white'/>"
1442 : " <Option name='STREAMABLE_OUTPUT' type='boolean' default='NO' "
1443 : "description='Enforce a mode compatible with a streamable file'/>"
1444 : " <Option name='GEOTIFF_KEYS_FLAVOR' type='string-select' "
1445 : "default='STANDARD' description='Which flavor of GeoTIFF keys must be "
1446 : "used'>"
1447 : " <Value>STANDARD</Value>"
1448 : " <Value>ESRI_PE</Value>"
1449 : " </Option>"
1450 : #if LIBGEOTIFF_VERSION >= 1600
1451 : " <Option name='GEOTIFF_VERSION' type='string-select' default='AUTO' "
1452 : "description='Which version of GeoTIFF must be used'>"
1453 : " <Value>AUTO</Value>"
1454 : " <Value>1.0</Value>"
1455 : " <Value>1.1</Value>"
1456 : " </Option>"
1457 : #endif
1458 : " <Option name='COLOR_TABLE_MULTIPLIER' type='string-select' "
1459 : "description='Multiplication factor to apply to go from GDAL color "
1460 : "table to TIFF color table' "
1461 : "default='257'>"
1462 : " <Value>1</Value>"
1463 : " <Value>256</Value>"
1464 : " <Value>257</Value>"
1465 : " </Option>"
1466 1741 : "</CreationOptionList>";
1467 :
1468 3482 : std::string osOvrOptions;
1469 : osOvrOptions = "<OverviewCreationOptionList>"
1470 : " <Option name='LOCATION' type='string-select'>"
1471 : " <Value>INTERNAL</Value>"
1472 : " <Value>EXTERNAL</Value>"
1473 : " <Value>RRD</Value>"
1474 : " </Option>"
1475 1741 : " <Option name='COMPRESS' type='string-select'>";
1476 1741 : osOvrOptions += osCompressValues;
1477 : osOvrOptions +=
1478 : " </Option>"
1479 : " <Option name='BLOCKSIZE' type='int' "
1480 : "description='Tile size in pixels' min='64'/>"
1481 : " <Option name='NUM_THREADS' type='string' description='Number of "
1482 1741 : "worker threads for compression. Can be set to ALL_CPUS' default='1'/>";
1483 1741 : if (bHasLZW || bHasDEFLATE || bHasZSTD)
1484 : osOvrOptions += " <Option name='PREDICTOR' type='int' "
1485 : "description='Predictor Type (1=default, 2=horizontal "
1486 : "differencing, 3=floating point prediction)' "
1487 1741 : "default='1'/>";
1488 1741 : if (bHasJPEG)
1489 : {
1490 : osOvrOptions +=
1491 : ""
1492 : " <Option name='JPEG_QUALITY' type='int' description='JPEG "
1493 : "quality 1-100' min='1' max='100' default='75'/>"
1494 : " <Option name='JPEGTABLESMODE' type='int' description='Content "
1495 : "of JPEGTABLES tag. 0=no JPEGTABLES tag, 1=Quantization tables "
1496 1741 : "only, 2=Huffman tables only, 3=Both' default='1'/>";
1497 : }
1498 1741 : if (bHasDEFLATE)
1499 : {
1500 : #ifdef LIBDEFLATE_SUPPORT
1501 : osOvrOptions +=
1502 : ""
1503 : " <Option name='ZLEVEL' type='int' description='DEFLATE "
1504 1741 : "compression level 1-12' min='1' max='12' default='6'/>";
1505 : #else
1506 : osOvrOptions +=
1507 : ""
1508 : " <Option name='ZLEVEL' type='int' description='DEFLATE "
1509 : "compression level 1-9' min='1' max='9' default='6'/>";
1510 : #endif
1511 : }
1512 1741 : if (bHasZSTD)
1513 : osOvrOptions +=
1514 : ""
1515 : " <Option name='ZSTD_LEVEL' type='int' description='ZSTD "
1516 : "compression level 1(fast)-22(slow)' min='1' max='22' "
1517 1741 : "default='9'/>";
1518 1741 : if (bHasLERC)
1519 : {
1520 : osOvrOptions +=
1521 : ""
1522 : " <Option name='MAX_Z_ERROR' type='float' description='Maximum "
1523 1741 : "error for LERC compression' default='0'/>";
1524 : }
1525 1741 : if (bHasWebP)
1526 : {
1527 : osOvrOptions +=
1528 : ""
1529 : #if WEBP_ENCODER_ABI_VERSION >= 0x0100
1530 : " <Option name='WEBP_LOSSLESS' type='boolean' "
1531 : "description='Whether lossless compression should be used' "
1532 : "default='FALSE'/>"
1533 : #endif
1534 : " <Option name='WEBP_LEVEL' type='int' description='WEBP quality "
1535 : "level. Low values result in higher compression ratios' "
1536 1741 : "default='" XSTRINGIFY(DEFAULT_WEBP_LEVEL) "'/>";
1537 : }
1538 : #ifdef HAVE_JXL
1539 : osOvrOptions +=
1540 : ""
1541 : " <Option name='JXL_LOSSLESS' type='boolean' description='Whether "
1542 : "JPEGXL compression should be lossless' default='YES'/>"
1543 : " <Option name='JXL_EFFORT' type='int' description='Level of effort "
1544 : "1(fast)-9(slow)' min='1' max='9' default='5'/>"
1545 : " <Option name='JXL_DISTANCE' type='float' description='Distance "
1546 : "level for lossy compression (0=mathematically lossless, 1.0=visually "
1547 1741 : "lossless, usual range [0.5,3])' default='1.0' min='0.01' max='25.0'/>";
1548 : #ifdef HAVE_JxlEncoderSetExtraChannelDistance
1549 : osOvrOptions += " <Option name='JXL_ALPHA_DISTANCE' type='float' "
1550 : "description='Distance level for alpha channel "
1551 : "(-1=same as non-alpha channels, "
1552 : "0=mathematically lossless, 1.0=visually lossless, "
1553 1741 : "usual range [0.5,3])' default='-1' min='-1' max='25.0'/>";
1554 : #endif
1555 : #endif
1556 : osOvrOptions +=
1557 : " <Option name='INTERLEAVE' type='string-select' default='PIXEL'>"
1558 : " <Value>BAND</Value>"
1559 : " <Value>PIXEL</Value>"
1560 : " </Option>"
1561 : " <Option name='PHOTOMETRIC' type='string-select'>"
1562 : " <Value>MINISBLACK</Value>"
1563 : " <Value>MINISWHITE</Value>"
1564 : " <Value>PALETTE</Value>"
1565 : " <Value>RGB</Value>"
1566 : " <Value>CMYK</Value>"
1567 : " <Value>YCBCR</Value>"
1568 : " <Value>CIELAB</Value>"
1569 : " <Value>ICCLAB</Value>"
1570 : " <Value>ITULAB</Value>"
1571 : " </Option>"
1572 : " <Option name='BIGTIFF' type='string-select' description='Force "
1573 : "creation of BigTIFF file (only for external overview)' "
1574 : "default='IF_NEEDED'>"
1575 : " <Value>YES</Value>"
1576 : " <Value>NO</Value>"
1577 : " <Value>IF_NEEDED</Value>"
1578 : " <Value>IF_SAFER</Value>"
1579 : " </Option>"
1580 : " <Option name='ALPHA' type='string-select' description='Mark first "
1581 : "extrasample as being alpha'>"
1582 : " <Value>NON-PREMULTIPLIED</Value>"
1583 : " <Value>PREMULTIPLIED</Value>"
1584 : " <Value>UNSPECIFIED</Value>"
1585 : " <Value aliasOf='NON-PREMULTIPLIED'>YES</Value>"
1586 : " <Value aliasOf='UNSPECIFIED'>NO</Value>"
1587 : " </Option>"
1588 1741 : "</OverviewCreationOptionList>";
1589 :
1590 : /* -------------------------------------------------------------------- */
1591 : /* Set the driver details. */
1592 : /* -------------------------------------------------------------------- */
1593 1741 : poDriver->SetDescription("GTiff");
1594 1741 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
1595 1741 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "GeoTIFF");
1596 1741 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/gtiff.html");
1597 1741 : poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/tiff");
1598 1741 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "tif");
1599 1741 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "tif tiff");
1600 1741 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
1601 : "Byte Int8 UInt16 Int16 UInt32 Int32 Float32 "
1602 1741 : "Float64 CInt16 CInt32 CFloat32 CFloat64");
1603 1741 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST, osOptions);
1604 1741 : poDriver->SetMetadataItem(GDAL_DMD_OVERVIEW_CREATIONOPTIONLIST,
1605 1741 : osOvrOptions.c_str());
1606 1741 : poDriver->SetMetadataItem(
1607 : GDAL_DMD_OPENOPTIONLIST,
1608 : "<OpenOptionList>"
1609 : " <Option name='NUM_THREADS' type='string' description='Number of "
1610 : "worker threads for compression. Can be set to ALL_CPUS' default='1'/>"
1611 : " <Option name='GEOTIFF_KEYS_FLAVOR' type='string-select' "
1612 : "default='STANDARD' description='Which flavor of GeoTIFF keys must be "
1613 : "used (for writing)'>"
1614 : " <Value>STANDARD</Value>"
1615 : " <Value>ESRI_PE</Value>"
1616 : " </Option>"
1617 : " <Option name='GEOREF_SOURCES' type='string' description='Comma "
1618 : "separated list made with values "
1619 : "INTERNAL/TABFILE/WORLDFILE/PAM/XML/NONE "
1620 : "that describe the priority order for georeferencing' "
1621 : "default='PAM,INTERNAL,TABFILE,WORLDFILE,XML'/>"
1622 : " <Option name='SPARSE_OK' type='boolean' description='Should empty "
1623 : "blocks be omitted on disk?' default='FALSE'/>"
1624 : " <Option name='IGNORE_COG_LAYOUT_BREAK' type='boolean' "
1625 : "description='Allow update mode on files with COG structure' "
1626 : "default='FALSE'/>"
1627 : " <Option name='COLOR_TABLE_MULTIPLIER' type='string-select' "
1628 : "description='Multiplication factor to apply to go from GDAL color "
1629 : "table to TIFF color table' "
1630 : "default='AUTO'>"
1631 : " <Value>AUTO</Value>"
1632 : " <Value>1</Value>"
1633 : " <Value>256</Value>"
1634 : " <Value>257</Value>"
1635 : " </Option>"
1636 1741 : "</OpenOptionList>");
1637 1741 : poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
1638 1741 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_SUBDATASETS, "YES");
1639 1741 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
1640 1741 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_ONLY_VISIBLE_AT_CLOSE_TIME,
1641 1741 : "YES");
1642 1741 : poDriver->SetMetadataItem(GDAL_DCAP_CAN_READ_AFTER_DELETE, "YES");
1643 :
1644 1741 : poDriver->SetMetadataItem(GDAL_DCAP_UPDATE, "YES");
1645 1741 : poDriver->SetMetadataItem(GDAL_DMD_UPDATE_ITEMS,
1646 : "GeoTransform SRS GCPs NoData "
1647 : "ColorInterpretation RasterValues "
1648 1741 : "DatasetMetadata BandMetadata");
1649 :
1650 : #ifdef INTERNAL_LIBTIFF
1651 1741 : poDriver->SetMetadataItem("LIBTIFF", "INTERNAL");
1652 : #else
1653 : poDriver->SetMetadataItem("LIBTIFF", TIFFLIB_VERSION_STR);
1654 : #endif
1655 :
1656 1741 : poDriver->SetMetadataItem("LIBGEOTIFF", XSTRINGIFY(LIBGEOTIFF_VERSION));
1657 :
1658 : #if defined(LERC_SUPPORT) && defined(LERC_VERSION_MAJOR)
1659 : poDriver->SetMetadataItem("LERC_VERSION_MAJOR",
1660 : XSTRINGIFY(LERC_VERSION_MAJOR), "LERC");
1661 : poDriver->SetMetadataItem("LERC_VERSION_MINOR",
1662 : XSTRINGIFY(LERC_VERSION_MINOR), "LERC");
1663 : poDriver->SetMetadataItem("LERC_VERSION_PATCH",
1664 : XSTRINGIFY(LERC_VERSION_PATCH), "LERC");
1665 : #endif
1666 :
1667 1741 : poDriver->SetMetadataItem(GDAL_DCAP_COORDINATE_EPOCH, "YES");
1668 :
1669 1741 : poDriver->pfnOpen = GTiffDataset::Open;
1670 1741 : poDriver->pfnCreate = GTiffDataset::Create;
1671 1741 : poDriver->pfnCreateCopy = GTiffDataset::CreateCopy;
1672 1741 : poDriver->pfnUnloadDriver = GDALDeregister_GTiff;
1673 1741 : poDriver->pfnIdentify = GTiffDataset::Identify;
1674 1741 : poDriver->pfnGetSubdatasetInfoFunc = GTiffDriverGetSubdatasetInfo;
1675 :
1676 1741 : GetGDALDriverManager()->RegisterDriver(poDriver);
1677 : }
|