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 42 : MAIN_START(argc, argv)
46 :
47 : {
48 42 : double dfGeoX = std::numeric_limits<double>::quiet_NaN();
49 42 : double dfGeoY = std::numeric_limits<double>::quiet_NaN();
50 80 : std::string osSrcFilename;
51 80 : std::string osSourceSRS;
52 80 : std::vector<int> anBandList;
53 42 : bool bAsXML = false, bLIFOnly = false;
54 42 : bool bQuiet = false, bValOnly = false;
55 42 : int nOverview = 0;
56 80 : CPLStringList aosOpenOptions;
57 80 : std::string osFieldSep;
58 42 : bool bIgnoreExtraInput = false;
59 42 : bool bEcho = false;
60 :
61 42 : GDALAllRegister();
62 42 : argc = GDALGeneralCmdLineProcessor(argc, &argv, 0);
63 42 : if (argc < 1)
64 1 : exit(-argc);
65 79 : CPLStringList aosArgv;
66 41 : aosArgv.Assign(argv, /* bAssign = */ true);
67 :
68 120 : GDALArgumentParser argParser(aosArgv[0], /* bForBinary=*/true);
69 :
70 41 : argParser.add_description(_("Raster query tool."));
71 :
72 41 : const char *pszEpilog =
73 : _("For more details, consult "
74 : "https://gdal.org/programs/gdallocationinfo.html");
75 41 : argParser.add_epilog(pszEpilog);
76 :
77 41 : argParser.add_argument("-xml").flag().store_into(bAsXML).help(
78 41 : _("Format the output report as XML."));
79 :
80 41 : argParser.add_argument("-lifonly")
81 41 : .flag()
82 41 : .store_into(bLIFOnly)
83 : .help(_("Only outputs filenames from the LocationInfo request against "
84 41 : "the database."));
85 :
86 41 : argParser.add_argument("-valonly")
87 41 : .flag()
88 41 : .store_into(bValOnly)
89 : .help(_("Only outputs pixel values of the selected pixel on each of "
90 41 : "the selected bands."));
91 :
92 41 : argParser.add_argument("-E").flag().store_into(bEcho).help(
93 : _("Enable Echo mode, where input coordinates are prepended to the "
94 41 : "output lines in -valonly mode."));
95 :
96 41 : argParser.add_argument("-field_sep")
97 82 : .metavar("<sep>")
98 41 : .store_into(osFieldSep)
99 : .help(_("Defines the field separator, used in -valonly mode, to "
100 41 : "separate different values."));
101 :
102 41 : argParser.add_argument("-ignore_extra_input")
103 41 : .flag()
104 41 : .store_into(bIgnoreExtraInput)
105 : .help(_("Set this flag to avoid extra non-numeric content at end of "
106 41 : "input lines."));
107 :
108 41 : argParser.add_argument("-b")
109 41 : .append()
110 82 : .metavar("<band>")
111 41 : .store_into(anBandList)
112 41 : .help(_("Select band(s)."));
113 :
114 41 : argParser.add_argument("-overview")
115 82 : .metavar("<overview_level>")
116 41 : .store_into(nOverview)
117 : .help(_("Query the (overview_level)th overview (overview_level=1 is "
118 41 : "the 1st overview)."));
119 :
120 79 : std::string osResampling;
121 41 : argParser.add_argument("-r")
122 41 : .store_into(osResampling)
123 82 : .metavar("nearest|bilinear|cubic|cubicspline")
124 41 : .help(_("Select an interpolation algorithm."));
125 :
126 : {
127 41 : auto &group = argParser.add_mutually_exclusive_group();
128 :
129 41 : group.add_argument("-l_srs")
130 82 : .metavar("<srs_def>")
131 41 : .store_into(osSourceSRS)
132 41 : .help(_("Coordinate system of the input x, y location."));
133 :
134 41 : group.add_argument("-geoloc")
135 41 : .flag()
136 5 : .action([&osSourceSRS](const std::string &)
137 46 : { osSourceSRS = "-geoloc"; })
138 : .help(_("Indicates input x,y points are in the georeferencing "
139 41 : "system of the image."));
140 :
141 41 : group.add_argument("-wgs84")
142 41 : .flag()
143 2 : .action([&osSourceSRS](const std::string &)
144 42 : { osSourceSRS = GetSRSAsWKT("WGS84"); })
145 41 : .help(_("Indicates input x,y points are WGS84 long, lat."));
146 : }
147 :
148 41 : argParser.add_open_options_argument(&aosOpenOptions);
149 :
150 41 : argParser.add_argument("srcfile")
151 82 : .metavar("<srcfile>")
152 41 : .nargs(1)
153 41 : .store_into(osSrcFilename)
154 41 : .help(_("The source GDAL raster datasource name."));
155 :
156 41 : argParser.add_argument("x")
157 82 : .metavar("<x>")
158 41 : .nargs(argparse::nargs_pattern::optional)
159 41 : .store_into(dfGeoX)
160 41 : .help(_("X location of target pixel."));
161 :
162 41 : argParser.add_argument("y")
163 82 : .metavar("<y>")
164 41 : .nargs(argparse::nargs_pattern::optional)
165 41 : .store_into(dfGeoY)
166 41 : .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 41 : 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 41 : if (bLIFOnly || bValOnly)
192 26 : bQuiet = true;
193 :
194 : // User specifies with 1-based index, but internally we use 0-based index
195 41 : --nOverview;
196 :
197 : // Deal with special characters
198 41 : osFieldSep = CPLString(osFieldSep)
199 82 : .replaceAll("\\t", '\t')
200 82 : .replaceAll("\\r", '\r')
201 41 : .replaceAll("\\n", '\n');
202 :
203 41 : 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 41 : const bool bIsXYSpecifiedAsArgument = !std::isnan(dfGeoX);
211 :
212 41 : if (bEcho && !bValOnly)
213 : {
214 1 : fprintf(stderr, "-E can only be used with -valonly\n");
215 1 : exit(1);
216 : }
217 40 : 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 39 : if (osFieldSep.empty())
225 : {
226 27 : osFieldSep = "\n";
227 : }
228 12 : 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 39 : osResampling.empty() ? GRIORA_NearestNeighbour
236 10 : : GDALRasterIOGetResampleAlg(osResampling.c_str());
237 39 : 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 38 : GDALDatasetH hSrcDS = GDALOpenEx(osSrcFilename.c_str(),
250 : GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR,
251 38 : nullptr, aosOpenOptions.List(), nullptr);
252 38 : if (hSrcDS == nullptr)
253 0 : exit(1);
254 :
255 : /* -------------------------------------------------------------------- */
256 : /* Setup coordinate transformation, if required */
257 : /* -------------------------------------------------------------------- */
258 38 : OGRSpatialReferenceH hSrcSRS = nullptr;
259 38 : OGRCoordinateTransformationH hCT = nullptr;
260 38 : 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 38 : if (anBandList.empty())
280 : {
281 87 : for (int i = 0; i < GDALGetRasterCount(hSrcDS); i++)
282 50 : anBandList.push_back(i + 1);
283 : }
284 :
285 : /* -------------------------------------------------------------------- */
286 : /* Turn the location into a pixel and line location. */
287 : /* -------------------------------------------------------------------- */
288 38 : bool inputAvailable = true;
289 76 : CPLString osXML;
290 : char szLine[1024];
291 38 : int nLine = 0;
292 38 : std::string osExtraContent;
293 :
294 38 : 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 38 : int nRetCode = 0;
349 46 : while (inputAvailable)
350 : {
351 : int iPixel, iLine;
352 46 : double dfPixel{0}, dfLine{0};
353 46 : const double dfXIn = dfGeoX;
354 46 : const double dfYIn = dfGeoY;
355 :
356 46 : if (hCT)
357 : {
358 4 : if (!OCTTransform(hCT, 1, &dfGeoX, &dfGeoY, nullptr))
359 0 : exit(1);
360 : }
361 :
362 46 : 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 37 : dfPixel = dfGeoX;
388 37 : dfLine = dfGeoY;
389 : }
390 46 : iPixel = static_cast<int>(floor(dfPixel));
391 46 : iLine = static_cast<int>(floor(dfLine));
392 :
393 : /* --------------------------------------------------------------------
394 : */
395 : /* Prepare report. */
396 : /* --------------------------------------------------------------------
397 : */
398 46 : CPLString osXmlLine;
399 :
400 46 : if (bAsXML)
401 : {
402 : osXmlLine.Printf("<Report pixel=\"%d\" line=\"%d\">", iPixel,
403 4 : iLine);
404 4 : osXML += osXmlLine;
405 4 : 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 42 : else if (!bQuiet)
415 : {
416 10 : printf("Report:\n");
417 20 : CPLString osPixel, osLine;
418 10 : if (eInterpolation == GRIORA_NearestNeighbour)
419 : {
420 7 : osPixel.Printf("%d", iPixel);
421 7 : osLine.Printf("%d", iLine);
422 : }
423 : else
424 : {
425 3 : osPixel.Printf("%.15g", dfPixel);
426 3 : osLine.Printf("%.15g", dfLine);
427 : }
428 10 : printf(" Location: (%sP,%sL)\n", osPixel.c_str(), osLine.c_str());
429 10 : if (!osExtraContent.empty())
430 : {
431 1 : printf(" Extra input: %s\n", osExtraContent.c_str());
432 : }
433 : }
434 32 : else if (bEcho)
435 : {
436 9 : printf("%.15g%s%.15g%s", dfXIn, osFieldSep.c_str(), dfYIn,
437 : osFieldSep.c_str());
438 : }
439 :
440 46 : bool bPixelReport = true;
441 :
442 42 : if (iPixel < 0 || iLine < 0 ||
443 130 : dfPixel > static_cast<double>(GDALGetRasterXSize(hSrcDS) + 1e-5) ||
444 42 : 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 105 : for (int i = 0; bPixelReport && i < static_cast<int>(anBandList.size());
469 : i++)
470 : {
471 59 : GDALRasterBandH hBand = GDALGetRasterBand(hSrcDS, anBandList[i]);
472 :
473 59 : int iPixelToQuery = iPixel;
474 59 : int iLineToQuery = iLine;
475 :
476 59 : double dfPixelToQuery = dfPixel;
477 59 : double dfLineToQuery = dfLine;
478 :
479 59 : 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 59 : if (hBand == nullptr)
511 0 : continue;
512 :
513 59 : if (bAsXML)
514 : {
515 6 : osXmlLine.Printf("<BandReport band=\"%d\">", anBandList[i]);
516 6 : osXML += osXmlLine;
517 : }
518 53 : else if (!bQuiet)
519 : {
520 12 : 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 118 : CPLString osItem;
530 :
531 59 : osItem.Printf("Pixel_%d_%d", iPixelToQuery, iLineToQuery);
532 :
533 : const char *pszLI =
534 59 : GDALGetMetadataItem(hBand, osItem, "LocationInfo");
535 :
536 59 : 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 59 : double adfPixel[2] = {0, 0};
577 59 : const bool bIsComplex = CPL_TO_BOOL(
578 : GDALDataTypeIsComplex(GDALGetRasterDataType(hBand)));
579 :
580 59 : CPLErrorReset();
581 59 : CPLErr err = GDALRasterInterpolateAtPoint(
582 : hBand, dfPixelToQuery, dfLineToQuery, eInterpolation,
583 : &adfPixel[0], &adfPixel[1]);
584 :
585 : // GDALRasterInterpolateAtPoint() returns false on nodata
586 59 : bool bIsNoData = false;
587 59 : if (err != CE_None && CPLGetLastErrorType() == CE_None)
588 : {
589 8 : int bHasNoData = FALSE;
590 : const double dfNoData =
591 8 : GDALGetRasterNoDataValue(hBand, &bHasNoData);
592 8 : if (bHasNoData)
593 : {
594 8 : bIsNoData = true;
595 8 : adfPixel[0] = adfPixel[1] = dfNoData;
596 8 : err = CE_None;
597 : }
598 : }
599 59 : if (err == CE_None)
600 : {
601 106 : CPLString osValue;
602 :
603 53 : if (bIsComplex)
604 0 : osValue.Printf("%.15g+%.15gi", adfPixel[0], adfPixel[1]);
605 : else
606 53 : osValue.Printf("%.15g", adfPixel[0]);
607 :
608 53 : if (bAsXML)
609 : {
610 4 : osXML += "<Value>";
611 4 : osXML += osValue;
612 4 : osXML += "</Value>";
613 : }
614 49 : else if (!bQuiet)
615 10 : printf(" Value: %s\n", osValue.c_str());
616 39 : else if (bValOnly)
617 : {
618 38 : if (i > 0)
619 12 : printf("%s", osFieldSep.c_str());
620 38 : printf("%s", osValue.c_str());
621 : }
622 :
623 : // Report unscaled if we have scale/offset values.
624 : int bSuccess;
625 :
626 53 : double dfOffset = GDALGetRasterOffset(hBand, &bSuccess);
627 : // TODO: Should we turn on checking of bSuccess?
628 : // Alternatively, delete these checks and put a comment as to
629 : // why checking bSuccess does not matter.
630 : #if 0
631 : if (bSuccess == FALSE)
632 : {
633 : CPLError( CE_Debug, CPLE_AppDefined,
634 : "Unable to get raster offset." );
635 : }
636 : #endif
637 53 : double dfScale = GDALGetRasterScale(hBand, &bSuccess);
638 : #if 0
639 : if (bSuccess == FALSE)
640 : {
641 : CPLError( CE_Debug, CPLE_AppDefined,
642 : "Unable to get raster scale." );
643 : }
644 : #endif
645 53 : if (!bIsNoData && (dfOffset != 0.0 || dfScale != 1.0))
646 : {
647 0 : adfPixel[0] = adfPixel[0] * dfScale + dfOffset;
648 :
649 0 : if (bIsComplex)
650 : {
651 0 : adfPixel[1] = adfPixel[1] * dfScale + dfOffset;
652 : osValue.Printf("%.15g+%.15gi", adfPixel[0],
653 0 : adfPixel[1]);
654 : }
655 : else
656 0 : osValue.Printf("%.15g", adfPixel[0]);
657 :
658 0 : if (bAsXML)
659 : {
660 0 : osXML += "<DescaledValue>";
661 0 : osXML += osValue;
662 0 : osXML += "</DescaledValue>";
663 : }
664 0 : else if (!bQuiet)
665 0 : printf(" Descaled Value: %s\n", osValue.c_str());
666 : }
667 : }
668 : else
669 : {
670 6 : nRetCode = 1;
671 6 : if (bAsXML)
672 : {
673 2 : osXML += "<IOError/>";
674 : }
675 4 : else if (bValOnly)
676 : {
677 2 : if (i > 0)
678 1 : printf("%s", osFieldSep.c_str());
679 : }
680 : }
681 59 : if (bAsXML)
682 6 : osXML += "</BandReport>";
683 : }
684 :
685 46 : osXML += "</Report>";
686 :
687 46 : if (bValOnly)
688 : {
689 31 : if (!osExtraContent.empty() && osFieldSep != "\n")
690 2 : printf("%s%s", osFieldSep.c_str(), osExtraContent.c_str());
691 31 : printf("\n");
692 : }
693 :
694 46 : if (bIsXYSpecifiedAsArgument)
695 24 : break;
696 :
697 22 : osExtraContent.clear();
698 22 : if (fgets(szLine, sizeof(szLine) - 1, stdin))
699 : {
700 8 : const CPLStringList aosTokens(CSLTokenizeString(szLine));
701 8 : const int nCount = aosTokens.size();
702 :
703 8 : ++nLine;
704 8 : if (nCount < 2)
705 : {
706 0 : fprintf(stderr, "Not enough values at line %d\n", nLine);
707 0 : continue;
708 : }
709 : else
710 : {
711 8 : dfGeoX = CPLAtof(aosTokens[0]);
712 8 : dfGeoY = CPLAtof(aosTokens[1]);
713 8 : if (!bIgnoreExtraInput)
714 : {
715 8 : for (int i = 2; i < nCount; ++i)
716 : {
717 0 : if (!osExtraContent.empty())
718 0 : osExtraContent += ' ';
719 0 : osExtraContent += aosTokens[i];
720 : }
721 8 : while (!osExtraContent.empty() &&
722 0 : isspace(static_cast<int>(osExtraContent.back())))
723 : {
724 0 : osExtraContent.pop_back();
725 : }
726 : }
727 : }
728 : }
729 : else
730 : {
731 14 : break;
732 : }
733 : }
734 :
735 : /* -------------------------------------------------------------------- */
736 : /* Finalize xml report and print. */
737 : /* -------------------------------------------------------------------- */
738 38 : if (bAsXML)
739 : {
740 4 : CPLXMLNode *psRoot = CPLParseXMLString(osXML);
741 4 : char *pszFormattedXML = CPLSerializeXMLTree(psRoot);
742 4 : CPLDestroyXMLNode(psRoot);
743 :
744 4 : printf("%s", pszFormattedXML);
745 4 : CPLFree(pszFormattedXML);
746 : }
747 :
748 : /* -------------------------------------------------------------------- */
749 : /* Cleanup */
750 : /* -------------------------------------------------------------------- */
751 38 : if (hCT)
752 : {
753 4 : OSRDestroySpatialReference(hSrcSRS);
754 4 : OCTDestroyCoordinateTransformation(hCT);
755 : }
756 :
757 38 : GDALClose(hSrcDS);
758 :
759 38 : GDALDumpOpenDatasets(stderr);
760 38 : GDALDestroyDriverManager();
761 :
762 38 : return nRetCode;
763 : }
764 :
765 0 : MAIN_END
|