LCOV - code coverage report
Current view: top level - apps - gdalwarp_bin.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 96 118 81.4 %
Date: 2024-11-21 22:18:42 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  High Performance Image Reprojector
       4             :  * Purpose:  Test program for high performance warper API.
       5             :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2002, i3 - information integration and imaging
       9             :  *                          Fort Collin, CO
      10             :  * Copyright (c) 2007-2015, Even Rouault <even dot rouault at spatialys.com>
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ****************************************************************************/
      14             : 
      15             : #include "cpl_string.h"
      16             : #include "cpl_error_internal.h"
      17             : #include "gdal_version.h"
      18             : #include "commonutils.h"
      19             : #include "gdal_utils_priv.h"
      20             : 
      21             : #include <vector>
      22             : 
      23             : /************************************************************************/
      24             : /*                               GDALExit()                             */
      25             : /*  This function exits and cleans up GDAL and OGR resources            */
      26             : /*  Perhaps it should be added to C api and used in all apps?           */
      27             : /************************************************************************/
      28             : 
      29           4 : static int GDALExit(int nCode)
      30             : {
      31           4 :     const char *pszDebug = CPLGetConfigOption("CPL_DEBUG", nullptr);
      32           4 :     if (pszDebug && (EQUAL(pszDebug, "ON") || EQUAL(pszDebug, "")))
      33             :     {
      34           0 :         GDALDumpOpenDatasets(stderr);
      35           0 :         CPLDumpSharedList(nullptr);
      36             :     }
      37             : 
      38           4 :     GDALDestroyDriverManager();
      39             : 
      40           4 :     OGRCleanupAll();
      41             : 
      42           4 :     exit(nCode);
      43             : }
      44             : 
      45             : /************************************************************************/
      46             : /*                               Usage()                                */
      47             : /************************************************************************/
      48             : 
      49           2 : static void Usage()
      50             : 
      51             : {
      52           2 :     fprintf(stderr, "%s\n", GDALWarpAppGetParserUsage().c_str());
      53           2 :     GDALExit(1);
      54           0 : }
      55             : 
      56             : /************************************************************************/
      57             : /*                          WarpTermProgress()                          */
      58             : /************************************************************************/
      59             : 
      60             : static int gnSrcCount = 0;
      61             : 
      62       14398 : static int CPL_STDCALL WarpTermProgress(double dfProgress,
      63             :                                         const char *pszMessage, void *)
      64             : {
      65       14398 :     static CPLString osLastMsg;
      66             :     static int iSrc = -1;
      67       14398 :     if (pszMessage == nullptr)
      68             :     {
      69           0 :         iSrc = 0;
      70             :     }
      71       14398 :     else if (pszMessage != osLastMsg)
      72             :     {
      73          98 :         if (!osLastMsg.empty())
      74           5 :             GDALTermProgress(1.0, nullptr, nullptr);
      75          98 :         printf("%s : ", pszMessage);
      76          98 :         osLastMsg = pszMessage;
      77          98 :         iSrc++;
      78             :     }
      79       14398 :     return GDALTermProgress(dfProgress * gnSrcCount - iSrc, nullptr, nullptr);
      80             : }
      81             : 
      82             : /************************************************************************/
      83             : /*                                main()                                */
      84             : /************************************************************************/
      85             : 
      86         104 : MAIN_START(argc, argv)
      87             : 
      88             : {
      89         104 :     EarlySetConfigOptions(argc, argv);
      90         104 :     CPLDebugOnly("GDAL", "Start");
      91             : 
      92             :     /* -------------------------------------------------------------------- */
      93             :     /*      Register standard GDAL drivers, and process generic GDAL        */
      94             :     /*      command options.                                                */
      95             :     /* -------------------------------------------------------------------- */
      96         104 :     GDALAllRegister();
      97         104 :     argc = GDALGeneralCmdLineProcessor(argc, &argv, 0);
      98         104 :     if (argc < 1)
      99           0 :         GDALExit(-argc);
     100             : 
     101             :     /* -------------------------------------------------------------------- */
     102             :     /*      Set optimal setting for best performance with huge input VRT.   */
     103             :     /*      The rationale for 450 is that typical Linux process allow       */
     104             :     /*      only 1024 file descriptors per process and we need to keep some */
     105             :     /*      spare for shared libraries, etc. so let's go down to 900.       */
     106             :     /*      And some datasets may need 2 file descriptors, so divide by 2   */
     107             :     /*      for security.                                                   */
     108             :     /* -------------------------------------------------------------------- */
     109         104 :     if (CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", nullptr) == nullptr)
     110             :     {
     111             : #if defined(__MACH__) && defined(__APPLE__)
     112             :         // On Mach, the default limit is 256 files per process
     113             :         // TODO We should eventually dynamically query the limit for all OS
     114             :         CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "100");
     115             : #else
     116         104 :         CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "450");
     117             : #endif
     118             :     }
     119             : 
     120         104 :     GDALWarpAppOptionsForBinary sOptionsForBinary;
     121             :     /* coverity[tainted_data] */
     122             :     GDALWarpAppOptions *psOptions =
     123         104 :         GDALWarpAppOptionsNew(argv + 1, &sOptionsForBinary);
     124         102 :     CSLDestroy(argv);
     125             : 
     126         102 :     if (psOptions == nullptr)
     127             :     {
     128           2 :         Usage();
     129             :     }
     130             : 
     131         195 :     if (sOptionsForBinary.aosSrcFiles.size() == 1 &&
     132         195 :         sOptionsForBinary.aosSrcFiles[0] == sOptionsForBinary.osDstFilename &&
     133           0 :         sOptionsForBinary.bOverwrite)
     134             :     {
     135           0 :         CPLError(CE_Failure, CPLE_IllegalArg,
     136             :                  "Source and destination datasets must be different.\n");
     137           0 :         GDALExit(1);
     138             :     }
     139             : 
     140             :     /* -------------------------------------------------------------------- */
     141             :     /*      Open source files.                                              */
     142             :     /* -------------------------------------------------------------------- */
     143         100 :     GDALDatasetH *pahSrcDS = nullptr;
     144         100 :     int nSrcCount = 0;
     145         203 :     for (int i = 0; i < sOptionsForBinary.aosSrcFiles.size(); ++i)
     146             :     {
     147         105 :         nSrcCount++;
     148             :         pahSrcDS = static_cast<GDALDatasetH *>(
     149         105 :             CPLRealloc(pahSrcDS, sizeof(GDALDatasetH) * nSrcCount));
     150         210 :         pahSrcDS[i] =
     151         105 :             GDALOpenEx(sOptionsForBinary.aosSrcFiles[i],
     152             :                        GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR,
     153         105 :                        sOptionsForBinary.aosAllowedInputDrivers.List(),
     154         105 :                        sOptionsForBinary.aosOpenOptions.List(), nullptr);
     155             : 
     156         105 :         if (pahSrcDS[i] == nullptr)
     157             :         {
     158           2 :             CPLError(CE_Failure, CPLE_OpenFailed,
     159             :                      "Failed to open source file %s\n",
     160             :                      sOptionsForBinary.aosSrcFiles[i]);
     161           4 :             while (nSrcCount--)
     162             :             {
     163           2 :                 GDALClose(pahSrcDS[nSrcCount]);
     164           2 :                 pahSrcDS[nSrcCount] = nullptr;
     165             :             }
     166           2 :             CPLFree(pahSrcDS);
     167           2 :             GDALWarpAppOptionsFree(psOptions);
     168           2 :             GDALExit(2);
     169             :         }
     170             :     }
     171             : 
     172             :     /* -------------------------------------------------------------------- */
     173             :     /*      Does the output dataset already exist?                          */
     174             :     /* -------------------------------------------------------------------- */
     175             : 
     176             :     /* FIXME ? source filename=target filename and -overwrite is definitely */
     177             :     /* an error. But I can't imagine of a valid case (without -overwrite), */
     178             :     /* where it would make sense. In doubt, let's keep that dubious
     179             :      * possibility... */
     180             : 
     181          98 :     bool bOutStreaming = false;
     182          98 :     if (sOptionsForBinary.osDstFilename == "/vsistdout/")
     183             :     {
     184           0 :         sOptionsForBinary.bQuiet = true;
     185           0 :         bOutStreaming = true;
     186             :     }
     187             : #ifdef S_ISFIFO
     188             :     else
     189             :     {
     190             :         VSIStatBufL sStat;
     191          98 :         if (VSIStatExL(sOptionsForBinary.osDstFilename.c_str(), &sStat,
     192         129 :                        VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
     193          31 :             S_ISFIFO(sStat.st_mode))
     194             :         {
     195           0 :             bOutStreaming = true;
     196             :         }
     197             :     }
     198             : #endif
     199             : 
     200          98 :     GDALDatasetH hDstDS = nullptr;
     201          98 :     if (bOutStreaming)
     202             :     {
     203           0 :         GDALWarpAppOptionsSetWarpOption(psOptions, "STREAMABLE_OUTPUT", "YES");
     204             :     }
     205             :     else
     206             :     {
     207         196 :         std::vector<CPLErrorHandlerAccumulatorStruct> aoErrors;
     208          98 :         CPLInstallErrorHandlerAccumulator(aoErrors);
     209          98 :         hDstDS = GDALOpenEx(
     210             :             sOptionsForBinary.osDstFilename.c_str(),
     211             :             GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR | GDAL_OF_UPDATE, nullptr,
     212          98 :             sOptionsForBinary.aosDestOpenOptions.List(), nullptr);
     213          98 :         CPLUninstallErrorHandlerAccumulator();
     214          98 :         if (hDstDS != nullptr)
     215             :         {
     216          31 :             for (size_t i = 0; i < aoErrors.size(); i++)
     217             :             {
     218           0 :                 CPLError(aoErrors[i].type, aoErrors[i].no, "%s",
     219           0 :                          aoErrors[i].msg.c_str());
     220             :             }
     221             :         }
     222             :     }
     223             : 
     224          98 :     if (hDstDS != nullptr && sOptionsForBinary.bOverwrite)
     225             :     {
     226          27 :         GDALClose(hDstDS);
     227          27 :         hDstDS = nullptr;
     228             :     }
     229             : 
     230          98 :     bool bCheckExistingDstFile =
     231          98 :         !bOutStreaming && hDstDS == nullptr && !sOptionsForBinary.bOverwrite;
     232             : 
     233          98 :     if (hDstDS != nullptr && sOptionsForBinary.bCreateOutput)
     234             :     {
     235           1 :         if (sOptionsForBinary.aosCreateOptions.FetchBool("APPEND_SUBDATASET",
     236             :                                                          false))
     237             :         {
     238           1 :             GDALClose(hDstDS);
     239           1 :             hDstDS = nullptr;
     240           1 :             bCheckExistingDstFile = false;
     241             :         }
     242             :         else
     243             :         {
     244           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     245             :                      "Output dataset %s exists,\n"
     246             :                      "but some command line options were provided indicating a "
     247             :                      "new dataset\n"
     248             :                      "should be created.  Please delete existing dataset and "
     249             :                      "run again.\n",
     250             :                      sOptionsForBinary.osDstFilename.c_str());
     251           0 :             GDALExit(1);
     252             :         }
     253             :     }
     254             : 
     255             :     /* Avoid overwriting an existing destination file that cannot be opened in
     256             :      */
     257             :     /* update mode with a new GTiff file */
     258          98 :     if (bCheckExistingDstFile)
     259             :     {
     260          41 :         CPLPushErrorHandler(CPLQuietErrorHandler);
     261          41 :         hDstDS = GDALOpen(sOptionsForBinary.osDstFilename.c_str(), GA_ReadOnly);
     262          41 :         CPLPopErrorHandler();
     263             : 
     264          41 :         if (hDstDS)
     265             :         {
     266           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     267             :                      "Output dataset %s exists, but cannot be opened in update "
     268             :                      "mode\n",
     269             :                      sOptionsForBinary.osDstFilename.c_str());
     270           0 :             GDALClose(hDstDS);
     271           0 :             GDALExit(1);
     272             :         }
     273             :     }
     274             : 
     275          98 :     if (!(sOptionsForBinary.bQuiet))
     276             :     {
     277          93 :         gnSrcCount = nSrcCount;
     278          93 :         GDALWarpAppOptionsSetProgress(psOptions, WarpTermProgress, nullptr);
     279          93 :         GDALWarpAppOptionsSetQuiet(psOptions, false);
     280             :     }
     281             : 
     282          98 :     int bUsageError = FALSE;
     283             :     GDALDatasetH hOutDS =
     284          98 :         GDALWarp(sOptionsForBinary.osDstFilename.c_str(), hDstDS, nSrcCount,
     285             :                  pahSrcDS, psOptions, &bUsageError);
     286          98 :     if (bUsageError)
     287           0 :         Usage();
     288          98 :     int nRetCode = (hOutDS) ? 0 : 1;
     289             : 
     290          98 :     GDALWarpAppOptionsFree(psOptions);
     291             : 
     292             :     // Close first hOutDS since it might reference sources (case of VRT)
     293          98 :     if (GDALClose(hOutDS ? hOutDS : hDstDS) != CE_None)
     294           0 :         nRetCode = 1;
     295             : 
     296         201 :     for (int i = 0; i < nSrcCount; i++)
     297             :     {
     298         103 :         GDALClose(pahSrcDS[i]);
     299             :     }
     300          98 :     CPLFree(pahSrcDS);
     301             : 
     302          98 :     GDALDumpOpenDatasets(stderr);
     303             : 
     304          98 :     OGRCleanupAll();
     305             : 
     306          98 :     return nRetCode;
     307             : }
     308             : 
     309           0 : MAIN_END

Generated by: LCOV version 1.14