LCOV - code coverage report
Current view: top level - frmts/gtiff - geotiff.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 492 555 88.6 %
Date: 2024-11-21 22:18:42 Functions: 33 35 94.3 %

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

Generated by: LCOV version 1.14