LCOV - code coverage report
Current view: top level - apps - gdallocationinfo.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 308 373 82.6 %
Date: 2024-11-21 22:18:42 Functions: 4 5 80.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  Command line raster query tool.
       5             :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2010, Frank Warmerdam <warmerdam@pobox.com>
       9             :  * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_string.h"
      15             : #include "cpl_minixml.h"
      16             : #include "gdal_version.h"
      17             : #include "gdal.h"
      18             : #include "gdal_priv.h"
      19             : #include "commonutils.h"
      20             : #include "ogr_spatialref.h"
      21             : #include "gdalargumentparser.h"
      22             : 
      23             : #include <cmath>
      24             : #include <limits>
      25             : #include <vector>
      26             : 
      27             : #include <cctype>
      28             : 
      29             : /************************************************************************/
      30             : /*                             GetSRSAsWKT                              */
      31             : /************************************************************************/
      32             : 
      33           1 : static std::string GetSRSAsWKT(const char *pszUserInput)
      34             : 
      35             : {
      36           2 :     OGRSpatialReference oSRS;
      37           1 :     oSRS.SetFromUserInput(pszUserInput);
      38           2 :     return oSRS.exportToWkt();
      39             : }
      40             : 
      41             : /************************************************************************/
      42             : /*                                main()                                */
      43             : /************************************************************************/
      44             : 
      45          34 : MAIN_START(argc, argv)
      46             : 
      47             : {
      48          34 :     double dfGeoX = std::numeric_limits<double>::quiet_NaN();
      49          34 :     double dfGeoY = std::numeric_limits<double>::quiet_NaN();
      50          64 :     std::string osSrcFilename;
      51          64 :     std::string osSourceSRS;
      52          64 :     std::vector<int> anBandList;
      53          34 :     bool bAsXML = false, bLIFOnly = false;
      54          34 :     bool bQuiet = false, bValOnly = false;
      55          34 :     int nOverview = 0;
      56          64 :     CPLStringList aosOpenOptions;
      57          64 :     std::string osFieldSep;
      58          34 :     bool bIgnoreExtraInput = false;
      59          34 :     bool bEcho = false;
      60             : 
      61          34 :     GDALAllRegister();
      62          34 :     argc = GDALGeneralCmdLineProcessor(argc, &argv, 0);
      63          34 :     if (argc < 1)
      64           0 :         exit(-argc);
      65          64 :     CPLStringList aosArgv;
      66          34 :     aosArgv.Assign(argv, /* bAssign = */ true);
      67             : 
      68          98 :     GDALArgumentParser argParser(aosArgv[0], /* bForBinary=*/true);
      69             : 
      70          34 :     argParser.add_description(_("Raster query tool."));
      71             : 
      72          34 :     const char *pszEpilog =
      73             :         _("For more details, consult "
      74             :           "https://gdal.org/programs/gdallocationinfo.html");
      75          34 :     argParser.add_epilog(pszEpilog);
      76             : 
      77          34 :     argParser.add_argument("-xml").flag().store_into(bAsXML).help(
      78          34 :         _("Format the output report as XML."));
      79             : 
      80          34 :     argParser.add_argument("-lifonly")
      81          34 :         .flag()
      82          34 :         .store_into(bLIFOnly)
      83             :         .help(_("Only outputs filenames from the LocationInfo request against "
      84          34 :                 "the database."));
      85             : 
      86          34 :     argParser.add_argument("-valonly")
      87          34 :         .flag()
      88          34 :         .store_into(bValOnly)
      89             :         .help(_("Only outputs pixel values of the selected pixel on each of "
      90          34 :                 "the selected bands."));
      91             : 
      92          34 :     argParser.add_argument("-E").flag().store_into(bEcho).help(
      93             :         _("Enable Echo mode, where input coordinates are prepended to the "
      94          34 :           "output lines in -valonly mode."));
      95             : 
      96          34 :     argParser.add_argument("-field_sep")
      97          68 :         .metavar("<sep>")
      98          34 :         .store_into(osFieldSep)
      99             :         .help(_("Defines the field separator, used in -valonly mode, to "
     100          34 :                 "separate different values."));
     101             : 
     102          34 :     argParser.add_argument("-ignore_extra_input")
     103          34 :         .flag()
     104          34 :         .store_into(bIgnoreExtraInput)
     105             :         .help(_("Set this flag to avoid extra non-numeric content at end of "
     106          34 :                 "input lines."));
     107             : 
     108          34 :     argParser.add_argument("-b")
     109          34 :         .append()
     110          68 :         .metavar("<band>")
     111          34 :         .store_into(anBandList)
     112          34 :         .help(_("Select band(s)."));
     113             : 
     114          34 :     argParser.add_argument("-overview")
     115          68 :         .metavar("<overview_level>")
     116          34 :         .store_into(nOverview)
     117             :         .help(_("Query the (overview_level)th overview (overview_level=1 is "
     118          34 :                 "the 1st overview)."));
     119             : 
     120          64 :     std::string osResampling;
     121          34 :     argParser.add_argument("-r")
     122          34 :         .store_into(osResampling)
     123          68 :         .metavar("nearest|bilinear|cubic|cubicspline")
     124          34 :         .help(_("Select an interpolation algorithm."));
     125             : 
     126             :     {
     127          34 :         auto &group = argParser.add_mutually_exclusive_group();
     128             : 
     129          34 :         group.add_argument("-l_srs")
     130          68 :             .metavar("<srs_def>")
     131          34 :             .store_into(osSourceSRS)
     132          34 :             .help(_("Coordinate system of the input x, y location."));
     133             : 
     134          34 :         group.add_argument("-geoloc")
     135          34 :             .flag()
     136           4 :             .action([&osSourceSRS](const std::string &)
     137          38 :                     { osSourceSRS = "-geoloc"; })
     138             :             .help(_("Indicates input x,y points are in the georeferencing "
     139          34 :                     "system of the image."));
     140             : 
     141          34 :         group.add_argument("-wgs84")
     142          34 :             .flag()
     143           2 :             .action([&osSourceSRS](const std::string &)
     144          35 :                     { osSourceSRS = GetSRSAsWKT("WGS84"); })
     145          34 :             .help(_("Indicates input x,y points are WGS84 long, lat."));
     146             :     }
     147             : 
     148          34 :     argParser.add_open_options_argument(&aosOpenOptions);
     149             : 
     150          34 :     argParser.add_argument("srcfile")
     151          68 :         .metavar("<srcfile>")
     152          34 :         .nargs(1)
     153          34 :         .store_into(osSrcFilename)
     154          34 :         .help(_("The source GDAL raster datasource name."));
     155             : 
     156          34 :     argParser.add_argument("x")
     157          68 :         .metavar("<x>")
     158          34 :         .nargs(argparse::nargs_pattern::optional)
     159          34 :         .store_into(dfGeoX)
     160          34 :         .help(_("X location of target pixel."));
     161             : 
     162          34 :     argParser.add_argument("y")
     163          68 :         .metavar("<y>")
     164          34 :         .nargs(argparse::nargs_pattern::optional)
     165          34 :         .store_into(dfGeoY)
     166          34 :         .help(_("Y location of target pixel."));
     167             : 
     168           0 :     const auto displayUsage = [&argParser]()
     169             :     {
     170           0 :         std::stringstream usageStringStream;
     171           0 :         usageStringStream << argParser.usage();
     172           0 :         std::cerr << CPLString(usageStringStream.str())
     173           0 :                          .replaceAll("<x> <y>", "[<x> <y>]")
     174           0 :                   << std::endl
     175           0 :                   << std::endl;
     176             :         std::cout << _("Note: ") << "gdallocationinfo"
     177           0 :                   << _(" --long-usage for full help.") << std::endl;
     178           0 :     };
     179             : 
     180             :     try
     181             :     {
     182          34 :         argParser.parse_args(aosArgv);
     183             :     }
     184           0 :     catch (const std::exception &err)
     185             :     {
     186           0 :         std::cerr << _("Error: ") << err.what() << std::endl;
     187           0 :         displayUsage();
     188           0 :         std::exit(1);
     189             :     }
     190             : 
     191          33 :     if (bLIFOnly || bValOnly)
     192          23 :         bQuiet = true;
     193             : 
     194             :     // User specifies with 1-based index, but internally we use 0-based index
     195          33 :     --nOverview;
     196             : 
     197             :     // Deal with special characters
     198          33 :     osFieldSep = CPLString(osFieldSep)
     199          66 :                      .replaceAll("\\t", '\t')
     200          66 :                      .replaceAll("\\r", '\r')
     201          33 :                      .replaceAll("\\n", '\n');
     202             : 
     203          33 :     if (!std::isnan(dfGeoX) && std::isnan(dfGeoY))
     204             :     {
     205           0 :         fprintf(stderr, "<y> should be specified when <x> is specified\n\n");
     206           0 :         displayUsage();
     207           0 :         exit(1);
     208             :     }
     209             : 
     210          33 :     const bool bIsXYSpecifiedAsArgument = !std::isnan(dfGeoX);
     211             : 
     212          33 :     if (bEcho && !bValOnly)
     213             :     {
     214           1 :         fprintf(stderr, "-E can only be used with -valonly\n");
     215           1 :         exit(1);
     216             :     }
     217          32 :     if (bEcho && osFieldSep.empty())
     218             :     {
     219           1 :         fprintf(stderr, "-E can only be used if -field_sep is specified (to a "
     220             :                         "non-newline value)\n");
     221           1 :         exit(1);
     222             :     }
     223             : 
     224          31 :     if (osFieldSep.empty())
     225             :     {
     226          22 :         osFieldSep = "\n";
     227             :     }
     228           9 :     else if (!bValOnly)
     229             :     {
     230           0 :         fprintf(stderr, "-field_sep can only be used with -valonly\n");
     231           0 :         exit(1);
     232             :     }
     233             : 
     234             :     const GDALRIOResampleAlg eInterpolation =
     235          31 :         osResampling.empty() ? GRIORA_NearestNeighbour
     236          10 :                              : GDALRasterIOGetResampleAlg(osResampling.c_str());
     237          31 :     if (eInterpolation != GRIORA_NearestNeighbour &&
     238           4 :         eInterpolation != GRIORA_Bilinear && eInterpolation != GRIORA_Cubic &&
     239             :         eInterpolation != GRIORA_CubicSpline)
     240             :     {
     241           1 :         fprintf(stderr, "-r can only be used with values nearest, bilinear, "
     242             :                         "cubic and cubicspline\n");
     243           1 :         exit(1);
     244             :     }
     245             : 
     246             :     /* -------------------------------------------------------------------- */
     247             :     /*      Open source file.                                               */
     248             :     /* -------------------------------------------------------------------- */
     249          30 :     GDALDatasetH hSrcDS = GDALOpenEx(osSrcFilename.c_str(),
     250             :                                      GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR,
     251          30 :                                      nullptr, aosOpenOptions.List(), nullptr);
     252          30 :     if (hSrcDS == nullptr)
     253           0 :         exit(1);
     254             : 
     255             :     /* -------------------------------------------------------------------- */
     256             :     /*      Setup coordinate transformation, if required                    */
     257             :     /* -------------------------------------------------------------------- */
     258          30 :     OGRSpatialReferenceH hSrcSRS = nullptr;
     259          30 :     OGRCoordinateTransformationH hCT = nullptr;
     260          30 :     if (!osSourceSRS.empty() && !EQUAL(osSourceSRS.c_str(), "-geoloc"))
     261             :     {
     262           4 :         hSrcSRS = OSRNewSpatialReference(nullptr);
     263           4 :         OGRErr err = OSRSetFromUserInput(hSrcSRS, osSourceSRS.c_str());
     264           4 :         if (err != OGRERR_NONE)
     265           0 :             exit(1);
     266           4 :         OSRSetAxisMappingStrategy(hSrcSRS, OAMS_TRADITIONAL_GIS_ORDER);
     267           4 :         auto hTrgSRS = GDALGetSpatialRef(hSrcDS);
     268           4 :         if (!hTrgSRS)
     269           0 :             exit(1);
     270             : 
     271           4 :         hCT = OCTNewCoordinateTransformation(hSrcSRS, hTrgSRS);
     272           4 :         if (hCT == nullptr)
     273           0 :             exit(1);
     274             :     }
     275             : 
     276             :     /* -------------------------------------------------------------------- */
     277             :     /*      If no bands were requested, we will query them all.             */
     278             :     /* -------------------------------------------------------------------- */
     279          30 :     if (anBandList.empty())
     280             :     {
     281          64 :         for (int i = 0; i < GDALGetRasterCount(hSrcDS); i++)
     282          35 :             anBandList.push_back(i + 1);
     283             :     }
     284             : 
     285             :     /* -------------------------------------------------------------------- */
     286             :     /*      Turn the location into a pixel and line location.               */
     287             :     /* -------------------------------------------------------------------- */
     288          30 :     bool inputAvailable = true;
     289          60 :     CPLString osXML;
     290             :     char szLine[1024];
     291          30 :     int nLine = 0;
     292          30 :     std::string osExtraContent;
     293             : 
     294          30 :     if (std::isnan(dfGeoX))
     295             :     {
     296             :         // Is it an interactive terminal ?
     297          14 :         if (CPLIsInteractive(stdin))
     298             :         {
     299           0 :             if (!osSourceSRS.empty())
     300             :             {
     301           0 :                 fprintf(stderr, "Enter X Y values separated by space, and "
     302             :                                 "press Return.\n");
     303             :             }
     304             :             else
     305             :             {
     306           0 :                 fprintf(stderr, "Enter pixel line values separated by space, "
     307             :                                 "and press Return.\n");
     308             :             }
     309             :         }
     310             : 
     311          14 :         if (fgets(szLine, sizeof(szLine) - 1, stdin))
     312             :         {
     313          28 :             const CPLStringList aosTokens(CSLTokenizeString(szLine));
     314          14 :             const int nCount = aosTokens.size();
     315             : 
     316          14 :             ++nLine;
     317          14 :             if (nCount < 2)
     318             :             {
     319           0 :                 fprintf(stderr, "Not enough values at line %d\n", nLine);
     320           0 :                 inputAvailable = false;
     321             :             }
     322             :             else
     323             :             {
     324          14 :                 dfGeoX = CPLAtof(aosTokens[0]);
     325          14 :                 dfGeoY = CPLAtof(aosTokens[1]);
     326          14 :                 if (!bIgnoreExtraInput)
     327             :                 {
     328          22 :                     for (int i = 2; i < nCount; ++i)
     329             :                     {
     330           9 :                         if (!osExtraContent.empty())
     331           4 :                             osExtraContent += ' ';
     332           9 :                         osExtraContent += aosTokens[i];
     333             :                     }
     334          18 :                     while (!osExtraContent.empty() &&
     335           5 :                            isspace(static_cast<int>(osExtraContent.back())))
     336             :                     {
     337           0 :                         osExtraContent.pop_back();
     338             :                     }
     339             :                 }
     340             :             }
     341             :         }
     342             :         else
     343             :         {
     344           0 :             inputAvailable = false;
     345             :         }
     346             :     }
     347             : 
     348          30 :     int nRetCode = 0;
     349          38 :     while (inputAvailable)
     350             :     {
     351             :         int iPixel, iLine;
     352          38 :         double dfPixel{0}, dfLine{0};
     353          38 :         const double dfXIn = dfGeoX;
     354          38 :         const double dfYIn = dfGeoY;
     355             : 
     356          38 :         if (hCT)
     357             :         {
     358           4 :             if (!OCTTransform(hCT, 1, &dfGeoX, &dfGeoY, nullptr))
     359           0 :                 exit(1);
     360             :         }
     361             : 
     362          38 :         if (!osSourceSRS.empty())
     363             :         {
     364           8 :             double adfGeoTransform[6] = {};
     365           8 :             if (GDALGetGeoTransform(hSrcDS, adfGeoTransform) != CE_None)
     366             :             {
     367           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     368             :                          "Cannot get geotransform");
     369           0 :                 exit(1);
     370             :             }
     371             : 
     372           8 :             double adfInvGeoTransform[6] = {};
     373           8 :             if (!GDALInvGeoTransform(adfGeoTransform, adfInvGeoTransform))
     374             :             {
     375           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     376             :                          "Cannot invert geotransform");
     377           0 :                 exit(1);
     378             :             }
     379             : 
     380           8 :             dfPixel = adfInvGeoTransform[0] + adfInvGeoTransform[1] * dfGeoX +
     381           8 :                       adfInvGeoTransform[2] * dfGeoY;
     382           8 :             dfLine = adfInvGeoTransform[3] + adfInvGeoTransform[4] * dfGeoX +
     383           8 :                      adfInvGeoTransform[5] * dfGeoY;
     384             :         }
     385             :         else
     386             :         {
     387          30 :             dfPixel = dfGeoX;
     388          30 :             dfLine = dfGeoY;
     389             :         }
     390          38 :         iPixel = static_cast<int>(floor(dfPixel));
     391          38 :         iLine = static_cast<int>(floor(dfLine));
     392             : 
     393             :         /* --------------------------------------------------------------------
     394             :          */
     395             :         /*      Prepare report. */
     396             :         /* --------------------------------------------------------------------
     397             :          */
     398          38 :         CPLString osXmlLine;
     399             : 
     400          38 :         if (bAsXML)
     401             :         {
     402             :             osXmlLine.Printf("<Report pixel=\"%d\" line=\"%d\">", iPixel,
     403           2 :                              iLine);
     404           2 :             osXML += osXmlLine;
     405           2 :             if (!osExtraContent.empty())
     406             :             {
     407             :                 char *pszEscaped =
     408           1 :                     CPLEscapeString(osExtraContent.c_str(), -1, CPLES_XML);
     409           2 :                 osXML += CPLString().Printf("  <ExtraInput>%s</ExtraInput>",
     410           1 :                                             pszEscaped);
     411           1 :                 CPLFree(pszEscaped);
     412             :             }
     413             :         }
     414          36 :         else if (!bQuiet)
     415             :         {
     416           7 :             printf("Report:\n");
     417          14 :             CPLString osPixel, osLine;
     418           7 :             if (eInterpolation == GRIORA_NearestNeighbour)
     419             :             {
     420           4 :                 osPixel.Printf("%d", iPixel);
     421           4 :                 osLine.Printf("%d", iLine);
     422             :             }
     423             :             else
     424             :             {
     425           3 :                 osPixel.Printf("%.15g", dfPixel);
     426           3 :                 osLine.Printf("%.15g", dfLine);
     427             :             }
     428           7 :             printf("  Location: (%sP,%sL)\n", osPixel.c_str(), osLine.c_str());
     429           7 :             if (!osExtraContent.empty())
     430             :             {
     431           1 :                 printf("  Extra input: %s\n", osExtraContent.c_str());
     432             :             }
     433             :         }
     434          29 :         else if (bEcho)
     435             :         {
     436           9 :             printf("%.15g%s%.15g%s", dfXIn, osFieldSep.c_str(), dfYIn,
     437             :                    osFieldSep.c_str());
     438             :         }
     439             : 
     440          38 :         bool bPixelReport = true;
     441             : 
     442          72 :         if (iPixel < 0 || iLine < 0 || iPixel >= GDALGetRasterXSize(hSrcDS) ||
     443          34 :             iLine >= GDALGetRasterYSize(hSrcDS))
     444             :         {
     445           4 :             if (bAsXML)
     446             :                 osXML += "<Alert>Location is off this file! No further details "
     447           0 :                          "to report.</Alert>";
     448           4 :             else if (bValOnly)
     449             :             {
     450           8 :                 for (int i = 1; i < static_cast<int>(anBandList.size()); i++)
     451             :                 {
     452           4 :                     printf("%s", osFieldSep.c_str());
     453             :                 }
     454             :             }
     455           0 :             else if (!bQuiet)
     456           0 :                 printf("\nLocation is off this file! No further details to "
     457             :                        "report.\n");
     458           4 :             bPixelReport = false;
     459           4 :             nRetCode = 1;
     460             :         }
     461             : 
     462             :         /* --------------------------------------------------------------------
     463             :          */
     464             :         /*      Process each band. */
     465             :         /* --------------------------------------------------------------------
     466             :          */
     467          82 :         for (int i = 0; bPixelReport && i < static_cast<int>(anBandList.size());
     468             :              i++)
     469             :         {
     470          44 :             GDALRasterBandH hBand = GDALGetRasterBand(hSrcDS, anBandList[i]);
     471             : 
     472          44 :             int iPixelToQuery = iPixel;
     473          44 :             int iLineToQuery = iLine;
     474             : 
     475          44 :             double dfPixelToQuery = dfPixel;
     476          44 :             double dfLineToQuery = dfLine;
     477             : 
     478          44 :             if (nOverview >= 0 && hBand != nullptr)
     479             :             {
     480           1 :                 GDALRasterBandH hOvrBand = GDALGetOverview(hBand, nOverview);
     481           1 :                 if (hOvrBand != nullptr)
     482             :                 {
     483           1 :                     int nOvrXSize = GDALGetRasterBandXSize(hOvrBand);
     484           1 :                     int nOvrYSize = GDALGetRasterBandYSize(hOvrBand);
     485           1 :                     iPixelToQuery = static_cast<int>(
     486           1 :                         0.5 +
     487           1 :                         1.0 * iPixel / GDALGetRasterXSize(hSrcDS) * nOvrXSize);
     488           1 :                     iLineToQuery = static_cast<int>(
     489           1 :                         0.5 +
     490           1 :                         1.0 * iLine / GDALGetRasterYSize(hSrcDS) * nOvrYSize);
     491           1 :                     if (iPixelToQuery >= nOvrXSize)
     492           0 :                         iPixelToQuery = nOvrXSize - 1;
     493           1 :                     if (iLineToQuery >= nOvrYSize)
     494           0 :                         iLineToQuery = nOvrYSize - 1;
     495           1 :                     dfPixelToQuery =
     496           1 :                         dfPixel / GDALGetRasterXSize(hSrcDS) * nOvrXSize;
     497           1 :                     dfLineToQuery =
     498           1 :                         dfLine / GDALGetRasterYSize(hSrcDS) * nOvrYSize;
     499             :                 }
     500             :                 else
     501             :                 {
     502           0 :                     CPLError(CE_Failure, CPLE_AppDefined,
     503             :                              "Cannot get overview %d of band %d", nOverview + 1,
     504           0 :                              anBandList[i]);
     505             :                 }
     506           1 :                 hBand = hOvrBand;
     507             :             }
     508             : 
     509          44 :             if (hBand == nullptr)
     510           0 :                 continue;
     511             : 
     512          44 :             if (bAsXML)
     513             :             {
     514           2 :                 osXmlLine.Printf("<BandReport band=\"%d\">", anBandList[i]);
     515           2 :                 osXML += osXmlLine;
     516             :             }
     517          42 :             else if (!bQuiet)
     518             :             {
     519           7 :                 printf("  Band %d:\n", anBandList[i]);
     520             :             }
     521             : 
     522             :             /* --------------------------------------------------------------------
     523             :              */
     524             :             /*      Request location info for this location.  It is possible */
     525             :             /*      only the VRT driver actually supports this. */
     526             :             /* --------------------------------------------------------------------
     527             :              */
     528          88 :             CPLString osItem;
     529             : 
     530          44 :             osItem.Printf("Pixel_%d_%d", iPixelToQuery, iLineToQuery);
     531             : 
     532             :             const char *pszLI =
     533          44 :                 GDALGetMetadataItem(hBand, osItem, "LocationInfo");
     534             : 
     535          44 :             if (pszLI != nullptr)
     536             :             {
     537           1 :                 if (bAsXML)
     538           0 :                     osXML += pszLI;
     539           1 :                 else if (!bQuiet)
     540           0 :                     printf("    %s\n", pszLI);
     541           1 :                 else if (bLIFOnly)
     542             :                 {
     543             :                     /* Extract all files, if any. */
     544             : 
     545           1 :                     CPLXMLNode *psRoot = CPLParseXMLString(pszLI);
     546             : 
     547           1 :                     if (psRoot != nullptr && psRoot->psChild != nullptr &&
     548           1 :                         psRoot->eType == CXT_Element &&
     549           1 :                         EQUAL(psRoot->pszValue, "LocationInfo"))
     550             :                     {
     551           1 :                         for (CPLXMLNode *psNode = psRoot->psChild;
     552           2 :                              psNode != nullptr; psNode = psNode->psNext)
     553             :                         {
     554           1 :                             if (psNode->eType == CXT_Element &&
     555           1 :                                 EQUAL(psNode->pszValue, "File") &&
     556           1 :                                 psNode->psChild != nullptr)
     557             :                             {
     558             :                                 char *pszUnescaped =
     559           1 :                                     CPLUnescapeString(psNode->psChild->pszValue,
     560             :                                                       nullptr, CPLES_XML);
     561           1 :                                 printf("%s\n", pszUnescaped);
     562           1 :                                 CPLFree(pszUnescaped);
     563             :                             }
     564             :                         }
     565             :                     }
     566           1 :                     CPLDestroyXMLNode(psRoot);
     567             :                 }
     568             :             }
     569             : 
     570             :             /* --------------------------------------------------------------------
     571             :              */
     572             :             /*      Report the pixel value of this band. */
     573             :             /* --------------------------------------------------------------------
     574             :              */
     575          44 :             double adfPixel[2] = {0, 0};
     576          44 :             const bool bIsComplex = CPL_TO_BOOL(
     577             :                 GDALDataTypeIsComplex(GDALGetRasterDataType(hBand)));
     578             : 
     579             :             CPLErr err;
     580          44 :             err = GDALRasterInterpolateAtPoint(hBand, dfPixelToQuery,
     581             :                                                dfLineToQuery, eInterpolation,
     582             :                                                &adfPixel[0], &adfPixel[1]);
     583             : 
     584          44 :             if (err == CE_None)
     585             :             {
     586          86 :                 CPLString osValue;
     587             : 
     588          43 :                 if (bIsComplex)
     589           0 :                     osValue.Printf("%.15g+%.15gi", adfPixel[0], adfPixel[1]);
     590             :                 else
     591          43 :                     osValue.Printf("%.15g", adfPixel[0]);
     592             : 
     593          43 :                 if (bAsXML)
     594             :                 {
     595           2 :                     osXML += "<Value>";
     596           2 :                     osXML += osValue;
     597           2 :                     osXML += "</Value>";
     598             :                 }
     599          41 :                 else if (!bQuiet)
     600           7 :                     printf("    Value: %s\n", osValue.c_str());
     601          34 :                 else if (bValOnly)
     602             :                 {
     603          34 :                     if (i > 0)
     604          10 :                         printf("%s", osFieldSep.c_str());
     605          34 :                     printf("%s", osValue.c_str());
     606             :                 }
     607             : 
     608             :                 // Report unscaled if we have scale/offset values.
     609             :                 int bSuccess;
     610             : 
     611          43 :                 double dfOffset = GDALGetRasterOffset(hBand, &bSuccess);
     612             :                 // TODO: Should we turn on checking of bSuccess?
     613             :                 // Alternatively, delete these checks and put a comment as to
     614             :                 // why checking bSuccess does not matter.
     615             : #if 0
     616             :                 if (bSuccess == FALSE)
     617             :                 {
     618             :                     CPLError( CE_Debug, CPLE_AppDefined,
     619             :                               "Unable to get raster offset." );
     620             :                 }
     621             : #endif
     622          43 :                 double dfScale = GDALGetRasterScale(hBand, &bSuccess);
     623             : #if 0
     624             :                 if (bSuccess == FALSE)
     625             :                 {
     626             :                     CPLError( CE_Debug, CPLE_AppDefined,
     627             :                               "Unable to get raster scale." );
     628             :                 }
     629             : #endif
     630          43 :                 if (dfOffset != 0.0 || dfScale != 1.0)
     631             :                 {
     632           0 :                     adfPixel[0] = adfPixel[0] * dfScale + dfOffset;
     633             : 
     634           0 :                     if (bIsComplex)
     635             :                     {
     636           0 :                         adfPixel[1] = adfPixel[1] * dfScale + dfOffset;
     637             :                         osValue.Printf("%.15g+%.15gi", adfPixel[0],
     638           0 :                                        adfPixel[1]);
     639             :                     }
     640             :                     else
     641           0 :                         osValue.Printf("%.15g", adfPixel[0]);
     642             : 
     643           0 :                     if (bAsXML)
     644             :                     {
     645           0 :                         osXML += "<DescaledValue>";
     646           0 :                         osXML += osValue;
     647           0 :                         osXML += "</DescaledValue>";
     648             :                     }
     649           0 :                     else if (!bQuiet)
     650           0 :                         printf("    Descaled Value: %s\n", osValue.c_str());
     651             :                 }
     652             :             }
     653             : 
     654          44 :             if (bAsXML)
     655           2 :                 osXML += "</BandReport>";
     656             :         }
     657             : 
     658          38 :         osXML += "</Report>";
     659             : 
     660          38 :         if (bValOnly)
     661             :         {
     662          28 :             if (!osExtraContent.empty() && osFieldSep != "\n")
     663           2 :                 printf("%s%s", osFieldSep.c_str(), osExtraContent.c_str());
     664          28 :             printf("\n");
     665             :         }
     666             : 
     667          38 :         if (bIsXYSpecifiedAsArgument)
     668          16 :             break;
     669             : 
     670          22 :         osExtraContent.clear();
     671          22 :         if (fgets(szLine, sizeof(szLine) - 1, stdin))
     672             :         {
     673           8 :             const CPLStringList aosTokens(CSLTokenizeString(szLine));
     674           8 :             const int nCount = aosTokens.size();
     675             : 
     676           8 :             ++nLine;
     677           8 :             if (nCount < 2)
     678             :             {
     679           0 :                 fprintf(stderr, "Not enough values at line %d\n", nLine);
     680           0 :                 continue;
     681             :             }
     682             :             else
     683             :             {
     684           8 :                 dfGeoX = CPLAtof(aosTokens[0]);
     685           8 :                 dfGeoY = CPLAtof(aosTokens[1]);
     686           8 :                 if (!bIgnoreExtraInput)
     687             :                 {
     688           8 :                     for (int i = 2; i < nCount; ++i)
     689             :                     {
     690           0 :                         if (!osExtraContent.empty())
     691           0 :                             osExtraContent += ' ';
     692           0 :                         osExtraContent += aosTokens[i];
     693             :                     }
     694           8 :                     while (!osExtraContent.empty() &&
     695           0 :                            isspace(static_cast<int>(osExtraContent.back())))
     696             :                     {
     697           0 :                         osExtraContent.pop_back();
     698             :                     }
     699             :                 }
     700             :             }
     701             :         }
     702             :         else
     703             :         {
     704          14 :             break;
     705             :         }
     706             :     }
     707             : 
     708             :     /* -------------------------------------------------------------------- */
     709             :     /*      Finalize xml report and print.                                  */
     710             :     /* -------------------------------------------------------------------- */
     711          30 :     if (bAsXML)
     712             :     {
     713           2 :         CPLXMLNode *psRoot = CPLParseXMLString(osXML);
     714           2 :         char *pszFormattedXML = CPLSerializeXMLTree(psRoot);
     715           2 :         CPLDestroyXMLNode(psRoot);
     716             : 
     717           2 :         printf("%s", pszFormattedXML);
     718           2 :         CPLFree(pszFormattedXML);
     719             :     }
     720             : 
     721             :     /* -------------------------------------------------------------------- */
     722             :     /*      Cleanup                                                         */
     723             :     /* -------------------------------------------------------------------- */
     724          30 :     if (hCT)
     725             :     {
     726           4 :         OSRDestroySpatialReference(hSrcSRS);
     727           4 :         OCTDestroyCoordinateTransformation(hCT);
     728             :     }
     729             : 
     730          30 :     GDALClose(hSrcDS);
     731             : 
     732          30 :     GDALDumpOpenDatasets(stderr);
     733          30 :     GDALDestroyDriverManager();
     734             : 
     735          30 :     return nRetCode;
     736             : }
     737             : 
     738           0 : MAIN_END

Generated by: LCOV version 1.14