LCOV - code coverage report
Current view: top level - apps - gdal_translate_bin.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 87 131 66.4 %
Date: 2025-12-21 22:14:19 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Utilities
       4             :  * Purpose:  GDAL Image Translator Program
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1998, 2002, Frank Warmerdam
       9             :  * Copyright (c) 2007-2014, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_string.h"
      15             : #include "gdal_version.h"
      16             : #include "gdal_priv.h"
      17             : #include "ogr_spatialref.h"
      18             : #include "commonutils.h"
      19             : #include "gdal_utils_priv.h"
      20             : 
      21             : /*  ******************************************************************* */
      22             : /*                               Usage()                                */
      23             : /* ******************************************************************** */
      24             : 
      25           4 : static void Usage()
      26             : {
      27           4 :     fprintf(stderr, "%s\n", GDALTranslateGetParserUsage().c_str());
      28             : 
      29           4 :     exit(1);
      30             : }
      31             : 
      32             : /************************************************************************/
      33             : /*                                main()                                */
      34             : /************************************************************************/
      35             : 
      36         150 : MAIN_START(argc, argv)
      37             : 
      38             : {
      39             :     /* Check strict compilation and runtime library version as we use C++ API */
      40         150 :     if (!GDAL_CHECK_VERSION(argv[0]))
      41           0 :         exit(1);
      42             : 
      43         150 :     EarlySetConfigOptions(argc, argv);
      44             : 
      45             :     /* -------------------------------------------------------------------- */
      46             :     /*      Register standard GDAL drivers, and process generic GDAL        */
      47             :     /*      command options.                                                */
      48             :     /* -------------------------------------------------------------------- */
      49         150 :     GDALAllRegister();
      50         150 :     argc = GDALGeneralCmdLineProcessor(argc, &argv, 0);
      51         150 :     if (argc < 1)
      52           3 :         exit(-argc);
      53             : 
      54             :     /* -------------------------------------------------------------------- */
      55             :     /*      Set optimal setting for best performance with huge input VRT.   */
      56             :     /*      The rationale for 450 is that typical Linux process allow       */
      57             :     /*      only 1024 file descriptors per process and we need to keep some */
      58             :     /*      spare for shared libraries, etc. so let's go down to 900.       */
      59             :     /*      And some datasets may need 2 file descriptors, so divide by 2   */
      60             :     /*      for security.                                                   */
      61             :     /* -------------------------------------------------------------------- */
      62         147 :     if (CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", nullptr) == nullptr)
      63             :     {
      64             : #if defined(__MACH__) && defined(__APPLE__)
      65             :         // On Mach, the default limit is 256 files per process
      66             :         // TODO We should eventually dynamically query the limit for all OS
      67             :         CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "100");
      68             : #else
      69         147 :         CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "450");
      70             : #endif
      71             :     }
      72             : 
      73         286 :     GDALTranslateOptionsForBinary sOptionsForBinary;
      74             :     GDALTranslateOptions *psOptions =
      75         147 :         GDALTranslateOptionsNew(argv + 1, &sOptionsForBinary);
      76         147 :     CSLDestroy(argv);
      77             : 
      78         147 :     if (psOptions == nullptr)
      79             :     {
      80           4 :         Usage();
      81             :     }
      82             : 
      83         143 :     if (sOptionsForBinary.osDest == "/vsistdout/")
      84             :     {
      85           0 :         sOptionsForBinary.bQuiet = true;
      86             :     }
      87             : 
      88         143 :     if (!(sOptionsForBinary.bQuiet))
      89             :     {
      90         134 :         GDALTranslateOptionsSetProgress(psOptions, GDALTermProgress, nullptr);
      91             :     }
      92             : 
      93         143 :     if (!sOptionsForBinary.osFormat.empty())
      94             :     {
      95             :         GDALDriverH hDriver =
      96          88 :             GDALGetDriverByName(sOptionsForBinary.osFormat.c_str());
      97          88 :         if (hDriver == nullptr)
      98             :         {
      99             :             auto poMissingDriver =
     100           0 :                 GetGDALDriverManager()->GetHiddenDriverByName(
     101             :                     sOptionsForBinary.osFormat.c_str());
     102           0 :             if (poMissingDriver)
     103             :             {
     104             :                 const std::string msg =
     105           0 :                     GDALGetMessageAboutMissingPluginDriver(poMissingDriver);
     106           0 :                 fprintf(stderr,
     107             :                         "Output driver `%s' not found but is known. However "
     108             :                         "plugin %s\n",
     109             :                         sOptionsForBinary.osFormat.c_str(), msg.c_str());
     110           0 :                 GDALDestroyDriverManager();
     111           0 :                 exit(1);
     112             :             }
     113             : 
     114           0 :             fprintf(stderr, "Output driver `%s' not recognised.\n",
     115             :                     sOptionsForBinary.osFormat.c_str());
     116           0 :             fprintf(stderr, "The following format drivers are enabled and "
     117             :                             "support writing:\n");
     118           0 :             for (int iDr = 0; iDr < GDALGetDriverCount(); iDr++)
     119             :             {
     120           0 :                 hDriver = GDALGetDriver(iDr);
     121             : 
     122           0 :                 if (GDALGetMetadataItem(hDriver, GDAL_DCAP_RASTER, nullptr) !=
     123           0 :                         nullptr &&
     124           0 :                     (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, nullptr) !=
     125           0 :                          nullptr ||
     126           0 :                      GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATECOPY,
     127             :                                          nullptr) != nullptr))
     128             :                 {
     129           0 :                     fprintf(stderr, "  %s: %s\n",
     130             :                             GDALGetDriverShortName(hDriver),
     131             :                             GDALGetDriverLongName(hDriver));
     132             :                 }
     133             :             }
     134             : 
     135           0 :             GDALTranslateOptionsFree(psOptions);
     136             : 
     137           0 :             GDALDestroyDriverManager();
     138           0 :             exit(1);
     139             :         }
     140             :     }
     141             : 
     142             :     /* -------------------------------------------------------------------- */
     143             :     /*      Attempt to open source file.                                    */
     144             :     /* -------------------------------------------------------------------- */
     145             : 
     146         144 :     if (EQUAL(sOptionsForBinary.osFormat.c_str(), "ZARR") &&
     147           1 :         CPLTestBool(sOptionsForBinary.aosCreateOptions.FetchNameValueDef(
     148             :             "CONVERT_TO_KERCHUNK_PARQUET_REFERENCE", "FALSE")))
     149             :     {
     150           0 :         sOptionsForBinary.osSource = "ZARR_DUMMY:" + sOptionsForBinary.osSource;
     151             :     }
     152             : 
     153             :     GDALDatasetH hDataset =
     154         143 :         GDALOpenEx(sOptionsForBinary.osSource.c_str(),
     155             :                    GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR,
     156         143 :                    sOptionsForBinary.aosAllowedInputDrivers.List(),
     157         143 :                    sOptionsForBinary.aosOpenOptions.List(), nullptr);
     158             : 
     159         143 :     if (hDataset == nullptr)
     160             :     {
     161           4 :         GDALDestroyDriverManager();
     162           4 :         exit(1);
     163             :     }
     164             : 
     165             :     /* -------------------------------------------------------------------- */
     166             :     /*      Handle subdatasets.                                             */
     167             :     /* -------------------------------------------------------------------- */
     168         416 :     if (!sOptionsForBinary.bCopySubDatasets &&
     169         138 :         GDALGetRasterCount(hDataset) == 0 &&
     170           0 :         CSLCount(GDALGetMetadata(hDataset, "SUBDATASETS")) > 0 &&
     171             :         // S104 and S111 drivers know how to handle a source dataset with subdatasets
     172             :         // and no input bands.
     173         277 :         !EQUAL(sOptionsForBinary.osFormat.c_str(), "S104") &&
     174           0 :         !EQUAL(sOptionsForBinary.osFormat.c_str(), "S111"))
     175             :     {
     176           0 :         fprintf(stderr, "Input file contains subdatasets. Please, select one "
     177             :                         "of them for reading.\n");
     178           0 :         GDALClose(hDataset);
     179           0 :         GDALDestroyDriverManager();
     180           0 :         exit(1);
     181             :     }
     182             : 
     183         139 :     int bUsageError = FALSE;
     184         139 :     GDALDatasetH hOutDS = nullptr;
     185         139 :     GDALDriverH hOutDriver = nullptr;
     186             : 
     187         139 :     if (sOptionsForBinary.osFormat.empty())
     188             :     {
     189          51 :         hOutDriver = GDALGetDriverByName(
     190         102 :             GetOutputDriverForRaster(sOptionsForBinary.osDest.c_str()));
     191             :     }
     192             :     else
     193             :     {
     194          88 :         hOutDriver = GDALGetDriverByName(sOptionsForBinary.osFormat.c_str());
     195             :     }
     196             : 
     197         139 :     if (hOutDriver == nullptr)
     198             :     {
     199           0 :         fprintf(stderr, "Output driver not found.\n");
     200           0 :         GDALClose(hDataset);
     201           0 :         GDALDestroyDriverManager();
     202           0 :         exit(1);
     203             :     }
     204             : 
     205             :     bool bCopyCreateSubDatasets =
     206         139 :         (GDALGetMetadataItem(hOutDriver, GDAL_DCAP_SUBCREATECOPY, nullptr) !=
     207         139 :          nullptr);
     208             : 
     209         140 :     if (sOptionsForBinary.bCopySubDatasets &&
     210           1 :         CSLCount(GDALGetMetadata(hDataset, "SUBDATASETS")) > 0)
     211             :     {
     212           1 :         if (bCopyCreateSubDatasets)
     213             :         {
     214             :             // GDAL sets the size of the dataset with subdatasets to 512x512
     215             :             // this removes the srcwin function from this operation
     216           0 :             hOutDS = GDALTranslate(sOptionsForBinary.osDest.c_str(), hDataset,
     217             :                                    psOptions, &bUsageError);
     218           0 :             GDALClose(hOutDS);
     219             :         }
     220             :         else
     221             :         {
     222           1 :             char **papszSubdatasets = GDALGetMetadata(hDataset, "SUBDATASETS");
     223           1 :             const int nSubdatasets = CSLCount(papszSubdatasets) / 2;
     224             :             char *pszSubDest = static_cast<char *>(
     225           1 :                 CPLMalloc(strlen(sOptionsForBinary.osDest.c_str()) + 32));
     226             : 
     227             :             const CPLString osPath =
     228           2 :                 CPLGetPathSafe(sOptionsForBinary.osDest.c_str());
     229             :             const CPLString osBasename =
     230           2 :                 CPLGetBasenameSafe(sOptionsForBinary.osDest.c_str());
     231             :             const CPLString osExtension =
     232           2 :                 CPLGetExtensionSafe(sOptionsForBinary.osDest.c_str());
     233           2 :             CPLString osTemp;
     234             : 
     235           1 :             const char *pszFormat = nullptr;
     236           1 :             if (nSubdatasets < 10)
     237             :             {
     238           1 :                 pszFormat = "%s_%d";
     239             :             }
     240           0 :             else if (nSubdatasets < 100)
     241             :             {
     242           0 :                 pszFormat = "%s_%002d";
     243             :             }
     244             :             else
     245             :             {
     246           0 :                 pszFormat = "%s_%003d";
     247             :             }
     248             : 
     249           1 :             const char *pszDest = pszSubDest;
     250             : 
     251           2 :             for (int i = 0; papszSubdatasets[i] != nullptr; i += 2)
     252             :             {
     253             :                 char *pszSource =
     254           1 :                     CPLStrdup(strstr(papszSubdatasets[i], "=") + 1);
     255           1 :                 osTemp = CPLSPrintf(pszFormat, osBasename.c_str(), i / 2 + 1);
     256           1 :                 osTemp = CPLFormFilenameSafe(osPath, osTemp, osExtension);
     257           1 :                 strcpy(pszSubDest, osTemp.c_str());
     258           1 :                 hDataset = GDALOpenEx(pszSource, GDAL_OF_RASTER, nullptr,
     259           1 :                                       sOptionsForBinary.aosOpenOptions.List(),
     260             :                                       nullptr);
     261           1 :                 CPLFree(pszSource);
     262           1 :                 if (!sOptionsForBinary.bQuiet)
     263           1 :                     printf("Input file size is %d, %d\n",
     264             :                            GDALGetRasterXSize(hDataset),
     265             :                            GDALGetRasterYSize(hDataset));
     266             :                 hOutDS =
     267           1 :                     GDALTranslate(pszDest, hDataset, psOptions, &bUsageError);
     268           1 :                 if (hOutDS == nullptr)
     269           0 :                     break;
     270           1 :                 GDALClose(hOutDS);
     271             :             }
     272             : 
     273           1 :             CPLFree(pszSubDest);
     274             :         }
     275             : 
     276           1 :         if (bUsageError == TRUE)
     277           0 :             Usage();
     278           1 :         GDALClose(hDataset);
     279           1 :         GDALTranslateOptionsFree(psOptions);
     280             : 
     281           1 :         GDALDestroy();
     282           1 :         return 0;
     283             :     }
     284             : 
     285         138 :     if (!sOptionsForBinary.bQuiet)
     286         130 :         printf("Input file size is %d, %d\n", GDALGetRasterXSize(hDataset),
     287             :                GDALGetRasterYSize(hDataset));
     288             : 
     289         138 :     hOutDS = GDALTranslate(sOptionsForBinary.osDest.c_str(), hDataset,
     290             :                            psOptions, &bUsageError);
     291         138 :     if (bUsageError == TRUE)
     292           0 :         Usage();
     293         138 :     int nRetCode = hOutDS ? 0 : 1;
     294             : 
     295             :     /* Close hOutDS before hDataset for the -f VRT case */
     296         138 :     if (GDALClose(hOutDS) != CE_None)
     297             :     {
     298           0 :         nRetCode = 1;
     299           0 :         if (CPLGetLastErrorType() == CE_None)
     300             :         {
     301           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     302             :                      "Unknown error occurred in GDALClose()");
     303             :         }
     304             :     }
     305         138 :     GDALClose(hDataset);
     306         138 :     GDALTranslateOptionsFree(psOptions);
     307             : 
     308         138 :     GDALDestroy();
     309             : 
     310         138 :     return nRetCode;
     311             : }
     312             : 
     313           0 : MAIN_END

Generated by: LCOV version 1.14