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

Generated by: LCOV version 1.14