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