LCOV - code coverage report
Current view: top level - apps - gdal_translate_bin.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 86 129 66.7 %
Date: 2025-05-15 13:16:46 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         146 : MAIN_START(argc, argv)
      37             : 
      38             : {
      39             :     /* Check strict compilation and runtime library version as we use C++ API */
      40         146 :     if (!GDAL_CHECK_VERSION(argv[0]))
      41           0 :         exit(1);
      42             : 
      43         146 :     EarlySetConfigOptions(argc, argv);
      44             : 
      45             :     /* -------------------------------------------------------------------- */
      46             :     /*      Register standard GDAL drivers, and process generic GDAL        */
      47             :     /*      command options.                                                */
      48             :     /* -------------------------------------------------------------------- */
      49         146 :     GDALAllRegister();
      50         146 :     argc = GDALGeneralCmdLineProcessor(argc, &argv, 0);
      51         146 :     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         143 :     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         143 :         CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "450");
      70             : #endif
      71             :     }
      72             : 
      73         277 :     GDALTranslateOptionsForBinary sOptionsForBinary;
      74             :     GDALTranslateOptions *psOptions =
      75         143 :         GDALTranslateOptionsNew(argv + 1, &sOptionsForBinary);
      76         143 :     CSLDestroy(argv);
      77             : 
      78         143 :     if (psOptions == nullptr)
      79             :     {
      80           4 :         Usage();
      81             :     }
      82             : 
      83         139 :     if (sOptionsForBinary.osDest == "/vsistdout/")
      84             :     {
      85           0 :         sOptionsForBinary.bQuiet = true;
      86             :     }
      87             : 
      88         139 :     if (!(sOptionsForBinary.bQuiet))
      89             :     {
      90         128 :         GDALTranslateOptionsSetProgress(psOptions, GDALTermProgress, nullptr);
      91             :     }
      92             : 
      93         139 :     if (!sOptionsForBinary.osFormat.empty())
      94             :     {
      95             :         GDALDriverH hDriver =
      96          82 :             GDALGetDriverByName(sOptionsForBinary.osFormat.c_str());
      97          82 :         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         140 :     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         139 :         GDALOpenEx(sOptionsForBinary.osSource.c_str(),
     155             :                    GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR,
     156         139 :                    sOptionsForBinary.aosAllowedInputDrivers.List(),
     157         139 :                    sOptionsForBinary.aosOpenOptions.List(), nullptr);
     158             : 
     159         139 :     if (hDataset == nullptr)
     160             :     {
     161           5 :         GDALDestroyDriverManager();
     162           5 :         exit(1);
     163             :     }
     164             : 
     165             :     /* -------------------------------------------------------------------- */
     166             :     /*      Handle subdatasets.                                             */
     167             :     /* -------------------------------------------------------------------- */
     168         401 :     if (!sOptionsForBinary.bCopySubDatasets &&
     169         134 :         GDALGetRasterCount(hDataset) == 0 &&
     170           0 :         CSLCount(GDALGetMetadata(hDataset, "SUBDATASETS")) > 0)
     171             :     {
     172           0 :         fprintf(stderr, "Input file contains subdatasets. Please, select one "
     173             :                         "of them for reading.\n");
     174           0 :         GDALClose(hDataset);
     175           0 :         GDALDestroyDriverManager();
     176           0 :         exit(1);
     177             :     }
     178             : 
     179         134 :     int bUsageError = FALSE;
     180         134 :     GDALDatasetH hOutDS = nullptr;
     181         134 :     GDALDriverH hOutDriver = nullptr;
     182             : 
     183         134 :     if (sOptionsForBinary.osFormat.empty())
     184             :     {
     185          52 :         hOutDriver = GDALGetDriverByName(
     186         104 :             GetOutputDriverForRaster(sOptionsForBinary.osDest.c_str()));
     187             :     }
     188             :     else
     189             :     {
     190          82 :         hOutDriver = GDALGetDriverByName(sOptionsForBinary.osFormat.c_str());
     191             :     }
     192             : 
     193         134 :     if (hOutDriver == nullptr)
     194             :     {
     195           0 :         fprintf(stderr, "Output driver not found.\n");
     196           0 :         GDALClose(hDataset);
     197           0 :         GDALDestroyDriverManager();
     198           0 :         exit(1);
     199             :     }
     200             : 
     201             :     bool bCopyCreateSubDatasets =
     202         134 :         (GDALGetMetadataItem(hOutDriver, GDAL_DCAP_SUBCREATECOPY, nullptr) !=
     203         134 :          nullptr);
     204             : 
     205         135 :     if (sOptionsForBinary.bCopySubDatasets &&
     206           1 :         CSLCount(GDALGetMetadata(hDataset, "SUBDATASETS")) > 0)
     207             :     {
     208           1 :         if (bCopyCreateSubDatasets)
     209             :         {
     210             :             // GDAL sets the size of the dataset with subdatasets to 512x512
     211             :             // this removes the srcwin function from this operation
     212           0 :             hOutDS = GDALTranslate(sOptionsForBinary.osDest.c_str(), hDataset,
     213             :                                    psOptions, &bUsageError);
     214           0 :             GDALClose(hOutDS);
     215             :         }
     216             :         else
     217             :         {
     218           1 :             char **papszSubdatasets = GDALGetMetadata(hDataset, "SUBDATASETS");
     219           1 :             const int nSubdatasets = CSLCount(papszSubdatasets) / 2;
     220             :             char *pszSubDest = static_cast<char *>(
     221           1 :                 CPLMalloc(strlen(sOptionsForBinary.osDest.c_str()) + 32));
     222             : 
     223             :             const CPLString osPath =
     224           2 :                 CPLGetPathSafe(sOptionsForBinary.osDest.c_str());
     225             :             const CPLString osBasename =
     226           2 :                 CPLGetBasenameSafe(sOptionsForBinary.osDest.c_str());
     227             :             const CPLString osExtension =
     228           2 :                 CPLGetExtensionSafe(sOptionsForBinary.osDest.c_str());
     229           2 :             CPLString osTemp;
     230             : 
     231           1 :             const char *pszFormat = nullptr;
     232           1 :             if (nSubdatasets < 10)
     233             :             {
     234           1 :                 pszFormat = "%s_%d";
     235             :             }
     236           0 :             else if (nSubdatasets < 100)
     237             :             {
     238           0 :                 pszFormat = "%s_%002d";
     239             :             }
     240             :             else
     241             :             {
     242           0 :                 pszFormat = "%s_%003d";
     243             :             }
     244             : 
     245           1 :             const char *pszDest = pszSubDest;
     246             : 
     247           2 :             for (int i = 0; papszSubdatasets[i] != nullptr; i += 2)
     248             :             {
     249             :                 char *pszSource =
     250           1 :                     CPLStrdup(strstr(papszSubdatasets[i], "=") + 1);
     251           1 :                 osTemp = CPLSPrintf(pszFormat, osBasename.c_str(), i / 2 + 1);
     252           1 :                 osTemp = CPLFormFilenameSafe(osPath, osTemp, osExtension);
     253           1 :                 strcpy(pszSubDest, osTemp.c_str());
     254           1 :                 hDataset = GDALOpenEx(pszSource, GDAL_OF_RASTER, nullptr,
     255           1 :                                       sOptionsForBinary.aosOpenOptions.List(),
     256             :                                       nullptr);
     257           1 :                 CPLFree(pszSource);
     258           1 :                 if (!sOptionsForBinary.bQuiet)
     259           1 :                     printf("Input file size is %d, %d\n",
     260             :                            GDALGetRasterXSize(hDataset),
     261             :                            GDALGetRasterYSize(hDataset));
     262             :                 hOutDS =
     263           1 :                     GDALTranslate(pszDest, hDataset, psOptions, &bUsageError);
     264           1 :                 if (hOutDS == nullptr)
     265           0 :                     break;
     266           1 :                 GDALClose(hOutDS);
     267             :             }
     268             : 
     269           1 :             CPLFree(pszSubDest);
     270             :         }
     271             : 
     272           1 :         if (bUsageError == TRUE)
     273           0 :             Usage();
     274           1 :         GDALClose(hDataset);
     275           1 :         GDALTranslateOptionsFree(psOptions);
     276             : 
     277           1 :         GDALDestroy();
     278           1 :         return 0;
     279             :     }
     280             : 
     281         133 :     if (!sOptionsForBinary.bQuiet)
     282         124 :         printf("Input file size is %d, %d\n", GDALGetRasterXSize(hDataset),
     283             :                GDALGetRasterYSize(hDataset));
     284             : 
     285         133 :     hOutDS = GDALTranslate(sOptionsForBinary.osDest.c_str(), hDataset,
     286             :                            psOptions, &bUsageError);
     287         133 :     if (bUsageError == TRUE)
     288           0 :         Usage();
     289         133 :     int nRetCode = hOutDS ? 0 : 1;
     290             : 
     291             :     /* Close hOutDS before hDataset for the -f VRT case */
     292         133 :     if (GDALClose(hOutDS) != CE_None)
     293             :     {
     294           0 :         nRetCode = 1;
     295           0 :         if (CPLGetLastErrorType() == CE_None)
     296             :         {
     297           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     298             :                      "Unknown error occurred in GDALClose()");
     299             :         }
     300             :     }
     301         133 :     GDALClose(hDataset);
     302         133 :     GDALTranslateOptionsFree(psOptions);
     303             : 
     304         133 :     GDALDestroy();
     305             : 
     306         133 :     return nRetCode;
     307             : }
     308             : 
     309           0 : MAIN_END

Generated by: LCOV version 1.14