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: 2026-02-01 11:59:10 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             :             CSLConstList papszSubdatasets =
     223           1 :                 GDALGetMetadata(hDataset, "SUBDATASETS");
     224           1 :             const int nSubdatasets = CSLCount(papszSubdatasets) / 2;
     225             :             char *pszSubDest = static_cast<char *>(
     226           1 :                 CPLMalloc(strlen(sOptionsForBinary.osDest.c_str()) + 32));
     227             : 
     228             :             const CPLString osPath =
     229           2 :                 CPLGetPathSafe(sOptionsForBinary.osDest.c_str());
     230             :             const CPLString osBasename =
     231           2 :                 CPLGetBasenameSafe(sOptionsForBinary.osDest.c_str());
     232             :             const CPLString osExtension =
     233           2 :                 CPLGetExtensionSafe(sOptionsForBinary.osDest.c_str());
     234           2 :             CPLString osTemp;
     235             : 
     236           1 :             const char *pszFormat = nullptr;
     237           1 :             if (nSubdatasets < 10)
     238             :             {
     239           1 :                 pszFormat = "%s_%d";
     240             :             }
     241           0 :             else if (nSubdatasets < 100)
     242             :             {
     243           0 :                 pszFormat = "%s_%002d";
     244             :             }
     245             :             else
     246             :             {
     247           0 :                 pszFormat = "%s_%003d";
     248             :             }
     249             : 
     250           1 :             const char *pszDest = pszSubDest;
     251             : 
     252           2 :             for (int i = 0; papszSubdatasets[i] != nullptr; i += 2)
     253             :             {
     254             :                 char *pszSource =
     255           1 :                     CPLStrdup(strstr(papszSubdatasets[i], "=") + 1);
     256           1 :                 osTemp = CPLSPrintf(pszFormat, osBasename.c_str(), i / 2 + 1);
     257           1 :                 osTemp = CPLFormFilenameSafe(osPath, osTemp, osExtension);
     258           1 :                 strcpy(pszSubDest, osTemp.c_str());
     259           1 :                 hDataset = GDALOpenEx(pszSource, GDAL_OF_RASTER, nullptr,
     260           1 :                                       sOptionsForBinary.aosOpenOptions.List(),
     261             :                                       nullptr);
     262           1 :                 CPLFree(pszSource);
     263           1 :                 if (!sOptionsForBinary.bQuiet)
     264           1 :                     printf("Input file size is %d, %d\n",
     265             :                            GDALGetRasterXSize(hDataset),
     266             :                            GDALGetRasterYSize(hDataset));
     267             :                 hOutDS =
     268           1 :                     GDALTranslate(pszDest, hDataset, psOptions, &bUsageError);
     269           1 :                 if (hOutDS == nullptr)
     270           0 :                     break;
     271           1 :                 GDALClose(hOutDS);
     272             :             }
     273             : 
     274           1 :             CPLFree(pszSubDest);
     275             :         }
     276             : 
     277           1 :         if (bUsageError == TRUE)
     278           0 :             Usage();
     279           1 :         GDALClose(hDataset);
     280           1 :         GDALTranslateOptionsFree(psOptions);
     281             : 
     282           1 :         GDALDestroy();
     283           1 :         return 0;
     284             :     }
     285             : 
     286         138 :     if (!sOptionsForBinary.bQuiet)
     287         130 :         printf("Input file size is %d, %d\n", GDALGetRasterXSize(hDataset),
     288             :                GDALGetRasterYSize(hDataset));
     289             : 
     290         138 :     hOutDS = GDALTranslate(sOptionsForBinary.osDest.c_str(), hDataset,
     291             :                            psOptions, &bUsageError);
     292         138 :     if (bUsageError == TRUE)
     293           0 :         Usage();
     294         138 :     int nRetCode = hOutDS ? 0 : 1;
     295             : 
     296             :     /* Close hOutDS before hDataset for the -f VRT case */
     297         138 :     if (GDALClose(hOutDS) != CE_None)
     298             :     {
     299           0 :         nRetCode = 1;
     300           0 :         if (CPLGetLastErrorType() == CE_None)
     301             :         {
     302           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     303             :                      "Unknown error occurred in GDALClose()");
     304             :         }
     305             :     }
     306         138 :     GDALClose(hDataset);
     307         138 :     GDALTranslateOptionsFree(psOptions);
     308             : 
     309         138 :     GDALDestroy();
     310             : 
     311         138 :     return nRetCode;
     312             : }
     313             : 
     314           0 : MAIN_END

Generated by: LCOV version 1.14