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

Generated by: LCOV version 1.14