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
|