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