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 35 : MAIN_START(argc, argv)
46 :
47 : {
48 35 : double dfGeoX = std::numeric_limits<double>::quiet_NaN();
49 35 : double dfGeoY = std::numeric_limits<double>::quiet_NaN();
50 66 : std::string osSrcFilename;
51 66 : std::string osSourceSRS;
52 66 : std::vector<int> anBandList;
53 35 : bool bAsXML = false, bLIFOnly = false;
54 35 : bool bQuiet = false, bValOnly = false;
55 35 : int nOverview = 0;
56 66 : CPLStringList aosOpenOptions;
57 66 : std::string osFieldSep;
58 35 : bool bIgnoreExtraInput = false;
59 35 : bool bEcho = false;
60 :
61 35 : GDALAllRegister();
62 35 : argc = GDALGeneralCmdLineProcessor(argc, &argv, 0);
63 35 : if (argc < 1)
64 1 : exit(-argc);
65 65 : CPLStringList aosArgv;
66 34 : aosArgv.Assign(argv, /* bAssign = */ true);
67 :
68 99 : 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 65 : 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 5 : .action([&osSourceSRS](const std::string &)
137 39 : { 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 34 : if (bLIFOnly || bValOnly)
192 23 : bQuiet = true;
193 :
194 : // User specifies with 1-based index, but internally we use 0-based index
195 34 : --nOverview;
196 :
197 : // Deal with special characters
198 34 : osFieldSep = CPLString(osFieldSep)
199 68 : .replaceAll("\\t", '\t')
200 68 : .replaceAll("\\r", '\r')
201 34 : .replaceAll("\\n", '\n');
202 :
203 34 : 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 34 : const bool bIsXYSpecifiedAsArgument = !std::isnan(dfGeoX);
211 :
212 34 : if (bEcho && !bValOnly)
213 : {
214 1 : fprintf(stderr, "-E can only be used with -valonly\n");
215 1 : exit(1);
216 : }
217 33 : 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 32 : if (osFieldSep.empty())
225 : {
226 23 : 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 32 : osResampling.empty() ? GRIORA_NearestNeighbour
236 10 : : GDALRasterIOGetResampleAlg(osResampling.c_str());
237 32 : 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 31 : GDALDatasetH hSrcDS = GDALOpenEx(osSrcFilename.c_str(),
250 : GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR,
251 31 : nullptr, aosOpenOptions.List(), nullptr);
252 31 : if (hSrcDS == nullptr)
253 0 : exit(1);
254 :
255 : /* -------------------------------------------------------------------- */
256 : /* Setup coordinate transformation, if required */
257 : /* -------------------------------------------------------------------- */
258 31 : OGRSpatialReferenceH hSrcSRS = nullptr;
259 31 : OGRCoordinateTransformationH hCT = nullptr;
260 31 : 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 31 : if (anBandList.empty())
280 : {
281 66 : for (int i = 0; i < GDALGetRasterCount(hSrcDS); i++)
282 36 : anBandList.push_back(i + 1);
283 : }
284 :
285 : /* -------------------------------------------------------------------- */
286 : /* Turn the location into a pixel and line location. */
287 : /* -------------------------------------------------------------------- */
288 31 : bool inputAvailable = true;
289 62 : CPLString osXML;
290 : char szLine[1024];
291 31 : int nLine = 0;
292 31 : std::string osExtraContent;
293 :
294 31 : 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 31 : int nRetCode = 0;
349 39 : while (inputAvailable)
350 : {
351 : int iPixel, iLine;
352 39 : double dfPixel{0}, dfLine{0};
353 39 : const double dfXIn = dfGeoX;
354 39 : const double dfYIn = dfGeoY;
355 :
356 39 : if (hCT)
357 : {
358 4 : if (!OCTTransform(hCT, 1, &dfGeoX, &dfGeoY, nullptr))
359 0 : exit(1);
360 : }
361 :
362 39 : if (!osSourceSRS.empty())
363 : {
364 9 : double adfGeoTransform[6] = {};
365 9 : 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 9 : double adfInvGeoTransform[6] = {};
373 9 : if (!GDALInvGeoTransform(adfGeoTransform, adfInvGeoTransform))
374 : {
375 0 : CPLError(CE_Failure, CPLE_AppDefined,
376 : "Cannot invert geotransform");
377 0 : exit(1);
378 : }
379 :
380 9 : dfPixel = adfInvGeoTransform[0] + adfInvGeoTransform[1] * dfGeoX +
381 9 : adfInvGeoTransform[2] * dfGeoY;
382 9 : dfLine = adfInvGeoTransform[3] + adfInvGeoTransform[4] * dfGeoX +
383 9 : adfInvGeoTransform[5] * dfGeoY;
384 : }
385 : else
386 : {
387 30 : dfPixel = dfGeoX;
388 30 : dfLine = dfGeoY;
389 : }
390 39 : iPixel = static_cast<int>(floor(dfPixel));
391 39 : iLine = static_cast<int>(floor(dfLine));
392 :
393 : /* --------------------------------------------------------------------
394 : */
395 : /* Prepare report. */
396 : /* --------------------------------------------------------------------
397 : */
398 39 : CPLString osXmlLine;
399 :
400 39 : 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 37 : else if (!bQuiet)
415 : {
416 8 : printf("Report:\n");
417 16 : CPLString osPixel, osLine;
418 8 : if (eInterpolation == GRIORA_NearestNeighbour)
419 : {
420 5 : osPixel.Printf("%d", iPixel);
421 5 : osLine.Printf("%d", iLine);
422 : }
423 : else
424 : {
425 3 : osPixel.Printf("%.15g", dfPixel);
426 3 : osLine.Printf("%.15g", dfLine);
427 : }
428 8 : printf(" Location: (%sP,%sL)\n", osPixel.c_str(), osLine.c_str());
429 8 : 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 39 : bool bPixelReport = true;
441 :
442 35 : if (iPixel < 0 || iLine < 0 ||
443 109 : dfPixel > static_cast<double>(GDALGetRasterXSize(hSrcDS) + 1e-5) ||
444 35 : dfLine > static_cast<double>(GDALGetRasterYSize(hSrcDS) + 1e-5))
445 : {
446 4 : if (bAsXML)
447 : osXML += "<Alert>Location is off this file! No further details "
448 0 : "to report.</Alert>";
449 4 : else if (bValOnly)
450 : {
451 8 : for (int i = 1; i < static_cast<int>(anBandList.size()); i++)
452 : {
453 4 : printf("%s", osFieldSep.c_str());
454 : }
455 : }
456 0 : else if (!bQuiet)
457 0 : printf("\nLocation is off this file! No further details to "
458 : "report.\n");
459 4 : bPixelReport = false;
460 4 : nRetCode = 1;
461 : }
462 :
463 : /* --------------------------------------------------------------------
464 : */
465 : /* Process each band. */
466 : /* --------------------------------------------------------------------
467 : */
468 84 : for (int i = 0; bPixelReport && i < static_cast<int>(anBandList.size());
469 : i++)
470 : {
471 45 : GDALRasterBandH hBand = GDALGetRasterBand(hSrcDS, anBandList[i]);
472 :
473 45 : int iPixelToQuery = iPixel;
474 45 : int iLineToQuery = iLine;
475 :
476 45 : double dfPixelToQuery = dfPixel;
477 45 : double dfLineToQuery = dfLine;
478 :
479 45 : if (nOverview >= 0 && hBand != nullptr)
480 : {
481 1 : GDALRasterBandH hOvrBand = GDALGetOverview(hBand, nOverview);
482 1 : if (hOvrBand != nullptr)
483 : {
484 1 : int nOvrXSize = GDALGetRasterBandXSize(hOvrBand);
485 1 : int nOvrYSize = GDALGetRasterBandYSize(hOvrBand);
486 1 : iPixelToQuery = static_cast<int>(
487 1 : 0.5 +
488 1 : 1.0 * iPixel / GDALGetRasterXSize(hSrcDS) * nOvrXSize);
489 1 : iLineToQuery = static_cast<int>(
490 1 : 0.5 +
491 1 : 1.0 * iLine / GDALGetRasterYSize(hSrcDS) * nOvrYSize);
492 1 : if (iPixelToQuery >= nOvrXSize)
493 0 : iPixelToQuery = nOvrXSize - 1;
494 1 : if (iLineToQuery >= nOvrYSize)
495 0 : iLineToQuery = nOvrYSize - 1;
496 1 : dfPixelToQuery =
497 1 : dfPixel / GDALGetRasterXSize(hSrcDS) * nOvrXSize;
498 1 : dfLineToQuery =
499 1 : dfLine / GDALGetRasterYSize(hSrcDS) * nOvrYSize;
500 : }
501 : else
502 : {
503 0 : CPLError(CE_Failure, CPLE_AppDefined,
504 : "Cannot get overview %d of band %d", nOverview + 1,
505 0 : anBandList[i]);
506 : }
507 1 : hBand = hOvrBand;
508 : }
509 :
510 45 : if (hBand == nullptr)
511 0 : continue;
512 :
513 45 : if (bAsXML)
514 : {
515 2 : osXmlLine.Printf("<BandReport band=\"%d\">", anBandList[i]);
516 2 : osXML += osXmlLine;
517 : }
518 43 : else if (!bQuiet)
519 : {
520 8 : printf(" Band %d:\n", anBandList[i]);
521 : }
522 :
523 : /* --------------------------------------------------------------------
524 : */
525 : /* Request location info for this location. It is possible */
526 : /* only the VRT driver actually supports this. */
527 : /* --------------------------------------------------------------------
528 : */
529 90 : CPLString osItem;
530 :
531 45 : osItem.Printf("Pixel_%d_%d", iPixelToQuery, iLineToQuery);
532 :
533 : const char *pszLI =
534 45 : GDALGetMetadataItem(hBand, osItem, "LocationInfo");
535 :
536 45 : if (pszLI != nullptr)
537 : {
538 1 : if (bAsXML)
539 0 : osXML += pszLI;
540 1 : else if (!bQuiet)
541 0 : printf(" %s\n", pszLI);
542 1 : else if (bLIFOnly)
543 : {
544 : /* Extract all files, if any. */
545 :
546 1 : CPLXMLNode *psRoot = CPLParseXMLString(pszLI);
547 :
548 1 : if (psRoot != nullptr && psRoot->psChild != nullptr &&
549 1 : psRoot->eType == CXT_Element &&
550 1 : EQUAL(psRoot->pszValue, "LocationInfo"))
551 : {
552 1 : for (CPLXMLNode *psNode = psRoot->psChild;
553 2 : psNode != nullptr; psNode = psNode->psNext)
554 : {
555 1 : if (psNode->eType == CXT_Element &&
556 1 : EQUAL(psNode->pszValue, "File") &&
557 1 : psNode->psChild != nullptr)
558 : {
559 : char *pszUnescaped =
560 1 : CPLUnescapeString(psNode->psChild->pszValue,
561 : nullptr, CPLES_XML);
562 1 : printf("%s\n", pszUnescaped);
563 1 : CPLFree(pszUnescaped);
564 : }
565 : }
566 : }
567 1 : CPLDestroyXMLNode(psRoot);
568 : }
569 : }
570 :
571 : /* --------------------------------------------------------------------
572 : */
573 : /* Report the pixel value of this band. */
574 : /* --------------------------------------------------------------------
575 : */
576 45 : double adfPixel[2] = {0, 0};
577 45 : const bool bIsComplex = CPL_TO_BOOL(
578 : GDALDataTypeIsComplex(GDALGetRasterDataType(hBand)));
579 :
580 : CPLErr err;
581 45 : err = GDALRasterInterpolateAtPoint(hBand, dfPixelToQuery,
582 : dfLineToQuery, eInterpolation,
583 : &adfPixel[0], &adfPixel[1]);
584 :
585 45 : if (err == CE_None)
586 : {
587 88 : CPLString osValue;
588 :
589 44 : if (bIsComplex)
590 0 : osValue.Printf("%.15g+%.15gi", adfPixel[0], adfPixel[1]);
591 : else
592 44 : osValue.Printf("%.15g", adfPixel[0]);
593 :
594 44 : if (bAsXML)
595 : {
596 2 : osXML += "<Value>";
597 2 : osXML += osValue;
598 2 : osXML += "</Value>";
599 : }
600 42 : else if (!bQuiet)
601 8 : printf(" Value: %s\n", osValue.c_str());
602 34 : else if (bValOnly)
603 : {
604 34 : if (i > 0)
605 10 : printf("%s", osFieldSep.c_str());
606 34 : printf("%s", osValue.c_str());
607 : }
608 :
609 : // Report unscaled if we have scale/offset values.
610 : int bSuccess;
611 :
612 44 : double dfOffset = GDALGetRasterOffset(hBand, &bSuccess);
613 : // TODO: Should we turn on checking of bSuccess?
614 : // Alternatively, delete these checks and put a comment as to
615 : // why checking bSuccess does not matter.
616 : #if 0
617 : if (bSuccess == FALSE)
618 : {
619 : CPLError( CE_Debug, CPLE_AppDefined,
620 : "Unable to get raster offset." );
621 : }
622 : #endif
623 44 : double dfScale = GDALGetRasterScale(hBand, &bSuccess);
624 : #if 0
625 : if (bSuccess == FALSE)
626 : {
627 : CPLError( CE_Debug, CPLE_AppDefined,
628 : "Unable to get raster scale." );
629 : }
630 : #endif
631 44 : if (dfOffset != 0.0 || dfScale != 1.0)
632 : {
633 0 : adfPixel[0] = adfPixel[0] * dfScale + dfOffset;
634 :
635 0 : if (bIsComplex)
636 : {
637 0 : adfPixel[1] = adfPixel[1] * dfScale + dfOffset;
638 : osValue.Printf("%.15g+%.15gi", adfPixel[0],
639 0 : adfPixel[1]);
640 : }
641 : else
642 0 : osValue.Printf("%.15g", adfPixel[0]);
643 :
644 0 : if (bAsXML)
645 : {
646 0 : osXML += "<DescaledValue>";
647 0 : osXML += osValue;
648 0 : osXML += "</DescaledValue>";
649 : }
650 0 : else if (!bQuiet)
651 0 : printf(" Descaled Value: %s\n", osValue.c_str());
652 : }
653 : }
654 :
655 45 : if (bAsXML)
656 2 : osXML += "</BandReport>";
657 : }
658 :
659 39 : osXML += "</Report>";
660 :
661 39 : if (bValOnly)
662 : {
663 28 : if (!osExtraContent.empty() && osFieldSep != "\n")
664 2 : printf("%s%s", osFieldSep.c_str(), osExtraContent.c_str());
665 28 : printf("\n");
666 : }
667 :
668 39 : if (bIsXYSpecifiedAsArgument)
669 17 : break;
670 :
671 22 : osExtraContent.clear();
672 22 : if (fgets(szLine, sizeof(szLine) - 1, stdin))
673 : {
674 8 : const CPLStringList aosTokens(CSLTokenizeString(szLine));
675 8 : const int nCount = aosTokens.size();
676 :
677 8 : ++nLine;
678 8 : if (nCount < 2)
679 : {
680 0 : fprintf(stderr, "Not enough values at line %d\n", nLine);
681 0 : continue;
682 : }
683 : else
684 : {
685 8 : dfGeoX = CPLAtof(aosTokens[0]);
686 8 : dfGeoY = CPLAtof(aosTokens[1]);
687 8 : if (!bIgnoreExtraInput)
688 : {
689 8 : for (int i = 2; i < nCount; ++i)
690 : {
691 0 : if (!osExtraContent.empty())
692 0 : osExtraContent += ' ';
693 0 : osExtraContent += aosTokens[i];
694 : }
695 8 : while (!osExtraContent.empty() &&
696 0 : isspace(static_cast<int>(osExtraContent.back())))
697 : {
698 0 : osExtraContent.pop_back();
699 : }
700 : }
701 : }
702 : }
703 : else
704 : {
705 14 : break;
706 : }
707 : }
708 :
709 : /* -------------------------------------------------------------------- */
710 : /* Finalize xml report and print. */
711 : /* -------------------------------------------------------------------- */
712 31 : if (bAsXML)
713 : {
714 2 : CPLXMLNode *psRoot = CPLParseXMLString(osXML);
715 2 : char *pszFormattedXML = CPLSerializeXMLTree(psRoot);
716 2 : CPLDestroyXMLNode(psRoot);
717 :
718 2 : printf("%s", pszFormattedXML);
719 2 : CPLFree(pszFormattedXML);
720 : }
721 :
722 : /* -------------------------------------------------------------------- */
723 : /* Cleanup */
724 : /* -------------------------------------------------------------------- */
725 31 : if (hCT)
726 : {
727 4 : OSRDestroySpatialReference(hSrcSRS);
728 4 : OCTDestroyCoordinateTransformation(hCT);
729 : }
730 :
731 31 : GDALClose(hSrcDS);
732 :
733 31 : GDALDumpOpenDatasets(stderr);
734 31 : GDALDestroyDriverManager();
735 :
736 31 : return nRetCode;
737 : }
738 :
739 0 : MAIN_END
|