1 : /******************************************************************************
2 : * $Id: gdal_misc.cpp 19588 2010-04-30 19:56:38Z rouault $
3 : *
4 : * Project: GDAL Core
5 : * Purpose: Free standing functions for GDAL.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Frank Warmerdam
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 "gdal_priv.h"
31 : #include "cpl_string.h"
32 : #include "cpl_minixml.h"
33 : #include "cpl_multiproc.h"
34 : #include <ctype.h>
35 : #include <string>
36 :
37 : CPL_CVSID("$Id: gdal_misc.cpp 19588 2010-04-30 19:56:38Z rouault $");
38 :
39 : #include "ogr_spatialref.h"
40 :
41 : /************************************************************************/
42 : /* __pure_virtual() */
43 : /* */
44 : /* The following is a gross hack to remove the last remaining */
45 : /* dependency on the GNU C++ standard library. */
46 : /************************************************************************/
47 :
48 : #ifdef __GNUC__
49 :
50 : extern "C"
51 0 : void __pure_virtual()
52 :
53 : {
54 0 : }
55 :
56 : #endif
57 :
58 : /************************************************************************/
59 : /* GDALDataTypeUnion() */
60 : /************************************************************************/
61 :
62 : /**
63 : * \brief Return the smallest data type that can fully express both input data
64 : * types.
65 : *
66 : * @param eType1
67 : * @param eType2
68 : *
69 : * @return a data type able to express eType1 and eType2.
70 : */
71 :
72 : GDALDataType CPL_STDCALL
73 621 : GDALDataTypeUnion( GDALDataType eType1, GDALDataType eType2 )
74 :
75 : {
76 : int bFloating, bComplex, nBits, bSigned;
77 :
78 621 : bComplex = GDALDataTypeIsComplex(eType1) | GDALDataTypeIsComplex(eType2);
79 :
80 621 : switch( eType1 )
81 : {
82 : case GDT_Byte:
83 401 : nBits = 8;
84 401 : bSigned = FALSE;
85 401 : bFloating = FALSE;
86 401 : break;
87 :
88 : case GDT_Int16:
89 : case GDT_CInt16:
90 0 : nBits = 16;
91 0 : bSigned = TRUE;
92 0 : bFloating = FALSE;
93 0 : break;
94 :
95 : case GDT_UInt16:
96 0 : nBits = 16;
97 0 : bSigned = FALSE;
98 0 : bFloating = FALSE;
99 0 : break;
100 :
101 : case GDT_Int32:
102 : case GDT_CInt32:
103 0 : nBits = 32;
104 0 : bSigned = TRUE;
105 0 : bFloating = FALSE;
106 0 : break;
107 :
108 : case GDT_UInt32:
109 0 : nBits = 32;
110 0 : bSigned = FALSE;
111 0 : bFloating = FALSE;
112 0 : break;
113 :
114 : case GDT_Float32:
115 : case GDT_CFloat32:
116 220 : nBits = 32;
117 220 : bSigned = TRUE;
118 220 : bFloating = TRUE;
119 220 : break;
120 :
121 : case GDT_Float64:
122 : case GDT_CFloat64:
123 0 : nBits = 64;
124 0 : bSigned = TRUE;
125 0 : bFloating = TRUE;
126 0 : break;
127 :
128 : default:
129 0 : CPLAssert( FALSE );
130 0 : return GDT_Unknown;
131 : }
132 :
133 621 : switch( eType2 )
134 : {
135 : case GDT_Byte:
136 153 : break;
137 :
138 : case GDT_Int16:
139 : case GDT_CInt16:
140 62 : nBits = MAX(nBits,16);
141 62 : bSigned = TRUE;
142 62 : break;
143 :
144 : case GDT_UInt16:
145 24 : nBits = MAX(nBits,16);
146 24 : break;
147 :
148 : case GDT_Int32:
149 : case GDT_CInt32:
150 266 : nBits = MAX(nBits,32);
151 266 : bSigned = TRUE;
152 266 : break;
153 :
154 : case GDT_UInt32:
155 23 : nBits = MAX(nBits,32);
156 23 : break;
157 :
158 : case GDT_Float32:
159 : case GDT_CFloat32:
160 46 : nBits = MAX(nBits,32);
161 46 : bSigned = TRUE;
162 46 : bFloating = TRUE;
163 46 : break;
164 :
165 : case GDT_Float64:
166 : case GDT_CFloat64:
167 47 : nBits = MAX(nBits,64);
168 47 : bSigned = TRUE;
169 47 : bFloating = TRUE;
170 47 : break;
171 :
172 : default:
173 0 : CPLAssert( FALSE );
174 0 : return GDT_Unknown;
175 : }
176 :
177 621 : if( nBits == 8 )
178 153 : return GDT_Byte;
179 468 : else if( nBits == 16 && bComplex )
180 22 : return GDT_CInt16;
181 446 : else if( nBits == 16 && bSigned )
182 40 : return GDT_Int16;
183 406 : else if( nBits == 16 && !bSigned )
184 24 : return GDT_UInt16;
185 382 : else if( nBits == 32 && bFloating && bComplex )
186 23 : return GDT_CFloat32;
187 359 : else if( nBits == 32 && bFloating )
188 243 : return GDT_Float32;
189 116 : else if( nBits == 32 && bComplex )
190 22 : return GDT_CInt32;
191 94 : else if( nBits == 32 && bSigned )
192 24 : return GDT_Int32;
193 70 : else if( nBits == 32 && !bSigned )
194 23 : return GDT_UInt32;
195 47 : else if( nBits == 64 && bComplex )
196 23 : return GDT_CFloat64;
197 : else
198 24 : return GDT_Float64;
199 : }
200 :
201 :
202 : /************************************************************************/
203 : /* GDALGetDataTypeSize() */
204 : /************************************************************************/
205 :
206 : /**
207 : * \brief Get data type size in bits.
208 : *
209 : * Returns the size of a a GDT_* type in bits, <b>not bytes</b>!
210 : *
211 : * @param data type, such as GDT_Byte.
212 : * @return the number of bits or zero if it is not recognised.
213 : */
214 :
215 6455599 : int CPL_STDCALL GDALGetDataTypeSize( GDALDataType eDataType )
216 :
217 : {
218 6455599 : switch( eDataType )
219 : {
220 : case GDT_Byte:
221 3335700 : return 8;
222 :
223 : case GDT_UInt16:
224 : case GDT_Int16:
225 1377023 : return 16;
226 :
227 : case GDT_UInt32:
228 : case GDT_Int32:
229 : case GDT_Float32:
230 : case GDT_CInt16:
231 1532405 : return 32;
232 :
233 : case GDT_Float64:
234 : case GDT_CInt32:
235 : case GDT_CFloat32:
236 38617 : return 64;
237 :
238 : case GDT_CFloat64:
239 171854 : return 128;
240 :
241 : default:
242 0 : return 0;
243 : }
244 : }
245 :
246 : /************************************************************************/
247 : /* GDALDataTypeIsComplex() */
248 : /************************************************************************/
249 :
250 : /**
251 : * \brief Is data type complex?
252 : *
253 : * @return TRUE if the passed type is complex (one of GDT_CInt16, GDT_CInt32,
254 : * GDT_CFloat32 or GDT_CFloat64), that is it consists of a real and imaginary
255 : * component.
256 : */
257 :
258 6044 : int CPL_STDCALL GDALDataTypeIsComplex( GDALDataType eDataType )
259 :
260 : {
261 6044 : switch( eDataType )
262 : {
263 : case GDT_CInt16:
264 : case GDT_CInt32:
265 : case GDT_CFloat32:
266 : case GDT_CFloat64:
267 344 : return TRUE;
268 :
269 : default:
270 5700 : return FALSE;
271 : }
272 : }
273 :
274 : /************************************************************************/
275 : /* GDALGetDataTypeName() */
276 : /************************************************************************/
277 :
278 : /**
279 : * \brief Get name of data type.
280 : *
281 : * Returns a symbolic name for the data type. This is essentially the
282 : * the enumerated item name with the GDT_ prefix removed. So GDT_Byte returns
283 : * "Byte". The returned strings are static strings and should not be modified
284 : * or freed by the application. These strings are useful for reporting
285 : * datatypes in debug statements, errors and other user output.
286 : *
287 : * @param eDataType type to get name of.
288 : * @return string corresponding to existing data type
289 : * or NULL pointer if invalid type given.
290 : */
291 :
292 14986 : const char * CPL_STDCALL GDALGetDataTypeName( GDALDataType eDataType )
293 :
294 : {
295 14986 : switch( eDataType )
296 : {
297 : case GDT_Unknown:
298 95 : return "Unknown";
299 :
300 : case GDT_Byte:
301 8321 : return "Byte";
302 :
303 : case GDT_UInt16:
304 883 : return "UInt16";
305 :
306 : case GDT_Int16:
307 806 : return "Int16";
308 :
309 : case GDT_UInt32:
310 733 : return "UInt32";
311 :
312 : case GDT_Int32:
313 692 : return "Int32";
314 :
315 : case GDT_Float32:
316 712 : return "Float32";
317 :
318 : case GDT_Float64:
319 575 : return "Float64";
320 :
321 : case GDT_CInt16:
322 557 : return "CInt16";
323 :
324 : case GDT_CInt32:
325 541 : return "CInt32";
326 :
327 : case GDT_CFloat32:
328 541 : return "CFloat32";
329 :
330 : case GDT_CFloat64:
331 530 : return "CFloat64";
332 :
333 : default:
334 0 : return NULL;
335 : }
336 : }
337 :
338 : /************************************************************************/
339 : /* GDALGetDataTypeByName() */
340 : /************************************************************************/
341 :
342 : /**
343 : * \brief Get data type by symbolic name.
344 : *
345 : * Returns a data type corresponding to the given symbolic name. This
346 : * function is opposite to the GDALGetDataTypeName().
347 : *
348 : * @param pszName string containing the symbolic name of the type.
349 : *
350 : * @return GDAL data type.
351 : */
352 :
353 339 : GDALDataType CPL_STDCALL GDALGetDataTypeByName( const char *pszName )
354 :
355 : {
356 339 : VALIDATE_POINTER1( pszName, "GDALGetDataTypeByName", GDT_Unknown );
357 :
358 : int iType;
359 :
360 921 : for( iType = 1; iType < GDT_TypeCount; iType++ )
361 : {
362 921 : if( GDALGetDataTypeName((GDALDataType)iType) != NULL
363 : && EQUAL(GDALGetDataTypeName((GDALDataType)iType), pszName) )
364 : {
365 339 : return (GDALDataType)iType;
366 : }
367 : }
368 :
369 0 : return GDT_Unknown;
370 : }
371 :
372 : /************************************************************************/
373 : /* GDALGetAsyncStatusTypeByName() */
374 : /************************************************************************/
375 : /**
376 : * Get AsyncStatusType by symbolic name.
377 : *
378 : * Returns a data type corresponding to the given symbolic name. This
379 : * function is opposite to the GDALGetAsyncStatusTypeName().
380 : *
381 : * @param pszName string containing the symbolic name of the type.
382 : *
383 : * @return GDAL AsyncStatus type.
384 : */
385 0 : GDALAsyncStatusType CPL_DLL CPL_STDCALL GDALGetAsyncStatusTypeByName( const char *pszName )
386 : {
387 0 : VALIDATE_POINTER1( pszName, "GDALGetAsyncStatusTypeByName", GARIO_ERROR);
388 :
389 : int iType;
390 :
391 0 : for( iType = 1; iType < GARIO_TypeCount; iType++ )
392 : {
393 0 : if( GDALGetAsyncStatusTypeName((GDALAsyncStatusType)iType) != NULL
394 : && EQUAL(GDALGetAsyncStatusTypeName((GDALAsyncStatusType)iType), pszName) )
395 : {
396 0 : return (GDALAsyncStatusType)iType;
397 : }
398 : }
399 :
400 0 : return GARIO_ERROR;
401 : }
402 :
403 :
404 : /************************************************************************/
405 : /* GDALGetAsyncStatusTypeName() */
406 : /************************************************************************/
407 :
408 : /**
409 : * Get name of AsyncStatus data type.
410 : *
411 : * Returns a symbolic name for the AsyncStatus data type. This is essentially the
412 : * the enumerated item name with the GARIO_ prefix removed. So GARIO_COMPLETE returns
413 : * "COMPLETE". The returned strings are static strings and should not be modified
414 : * or freed by the application. These strings are useful for reporting
415 : * datatypes in debug statements, errors and other user output.
416 : *
417 : * @param eAsyncStatusType type to get name of.
418 : * @return string corresponding to type.
419 : */
420 :
421 0 : const char * CPL_STDCALL GDALGetAsyncStatusTypeName( GDALAsyncStatusType eAsyncStatusType )
422 :
423 : {
424 0 : switch( eAsyncStatusType )
425 : {
426 : case GARIO_PENDING:
427 0 : return "PENDING";
428 :
429 : case GARIO_UPDATE:
430 0 : return "UPDATE";
431 :
432 : case GARIO_ERROR:
433 0 : return "ERROR";
434 :
435 : case GARIO_COMPLETE:
436 0 : return "COMPLETE";
437 : default:
438 0 : return NULL;
439 : }
440 : }
441 :
442 : /************************************************************************/
443 : /* GDALGetPaletteInterpretationName() */
444 : /************************************************************************/
445 :
446 : /**
447 : * \brief Get name of palette interpretation
448 : *
449 : * Returns a symbolic name for the palette interpretation. This is the
450 : * the enumerated item name with the GPI_ prefix removed. So GPI_Gray returns
451 : * "Gray". The returned strings are static strings and should not be modified
452 : * or freed by the application.
453 : *
454 : * @param eInterp palette interpretation to get name of.
455 : * @return string corresponding to palette interpretation.
456 : */
457 :
458 4 : const char *GDALGetPaletteInterpretationName( GDALPaletteInterp eInterp )
459 :
460 : {
461 4 : switch( eInterp )
462 : {
463 : case GPI_Gray:
464 0 : return "Gray";
465 :
466 : case GPI_RGB:
467 4 : return "RGB";
468 :
469 : case GPI_CMYK:
470 0 : return "CMYK";
471 :
472 : case GPI_HLS:
473 0 : return "HLS";
474 :
475 : default:
476 0 : return "Unknown";
477 : }
478 : }
479 :
480 : /************************************************************************/
481 : /* GDALGetColorInterpretationName() */
482 : /************************************************************************/
483 :
484 : /**
485 : * \brief Get name of color interpretation
486 : *
487 : * Returns a symbolic name for the color interpretation. This is derived from
488 : * the enumerated item name with the GCI_ prefix removed, but there are some
489 : * variations. So GCI_GrayIndex returns "Gray" and GCI_RedBand returns "Red".
490 : * The returned strings are static strings and should not be modified
491 : * or freed by the application.
492 : *
493 : * @param eInterp color interpretation to get name of.
494 : * @return string corresponding to color interpretation
495 : * or NULL pointer if invalid enumerator given.
496 : */
497 :
498 1405 : const char *GDALGetColorInterpretationName( GDALColorInterp eInterp )
499 :
500 : {
501 1405 : switch( eInterp )
502 : {
503 : case GCI_Undefined:
504 357 : return "Undefined";
505 :
506 : case GCI_GrayIndex:
507 595 : return "Gray";
508 :
509 : case GCI_PaletteIndex:
510 95 : return "Palette";
511 :
512 : case GCI_RedBand:
513 114 : return "Red";
514 :
515 : case GCI_GreenBand:
516 88 : return "Green";
517 :
518 : case GCI_BlueBand:
519 68 : return "Blue";
520 :
521 : case GCI_AlphaBand:
522 31 : return "Alpha";
523 :
524 : case GCI_HueBand:
525 6 : return "Hue";
526 :
527 : case GCI_SaturationBand:
528 6 : return "Saturation";
529 :
530 : case GCI_LightnessBand:
531 6 : return "Lightness";
532 :
533 : case GCI_CyanBand:
534 6 : return "Cyan";
535 :
536 : case GCI_MagentaBand:
537 6 : return "Magenta";
538 :
539 : case GCI_YellowBand:
540 6 : return "Yellow";
541 :
542 : case GCI_BlackBand:
543 6 : return "Black";
544 :
545 : case GCI_YCbCr_YBand:
546 7 : return "YCbCr_Y";
547 :
548 : case GCI_YCbCr_CbBand:
549 5 : return "YCbCr_Cb";
550 :
551 : case GCI_YCbCr_CrBand:
552 3 : return "YCbCr_Cr";
553 :
554 : default:
555 0 : return "Unknown";
556 : }
557 : }
558 :
559 : /************************************************************************/
560 : /* GDALGetColorInterpretationByName() */
561 : /************************************************************************/
562 :
563 : /**
564 : * \brief Get color interpreation by symbolic name.
565 : *
566 : * Returns a color interpreation corresponding to the given symbolic name. This
567 : * function is opposite to the GDALGetColorInterpretationName().
568 : *
569 : * @param pszName string containing the symbolic name of the color interpretation.
570 : *
571 : * @return GDAL color interpretation.
572 : *
573 : * @since GDAL 1.7.0
574 : */
575 :
576 355 : GDALColorInterp GDALGetColorInterpretationByName( const char *pszName )
577 :
578 : {
579 355 : VALIDATE_POINTER1( pszName, "GDALGetColorInterpretationByName", GCI_Undefined );
580 :
581 : int iType;
582 :
583 1058 : for( iType = 0; iType <= GCI_Max; iType++ )
584 : {
585 1058 : if( EQUAL(GDALGetColorInterpretationName((GDALColorInterp)iType), pszName) )
586 : {
587 355 : return (GDALColorInterp)iType;
588 : }
589 : }
590 :
591 0 : return GCI_Undefined;
592 : }
593 :
594 : /************************************************************************/
595 : /* GDALDummyProgress() */
596 : /************************************************************************/
597 :
598 : /**
599 : * \brief Stub progress function.
600 : *
601 : * This is a stub (does nothing) implementation of the GDALProgressFunc()
602 : * semantics. It is primarily useful for passing to functions that take
603 : * a GDALProgressFunc() argument but for which the application does not want
604 : * to use one of the other progress functions that actually do something.
605 : */
606 :
607 : int CPL_STDCALL GDALDummyProgress( double dfComplete, const char *pszMessage,
608 75096 : void *pData )
609 :
610 : {
611 75096 : return TRUE;
612 : }
613 :
614 : /************************************************************************/
615 : /* GDALScaledProgress() */
616 : /************************************************************************/
617 : typedef struct {
618 : GDALProgressFunc pfnProgress;
619 : void *pData;
620 : double dfMin;
621 : double dfMax;
622 : } GDALScaledProgressInfo;
623 :
624 : /**
625 : * \brief Scaled progress transformer.
626 : *
627 : * This is the progress function that should be passed along with the
628 : * callback data returned by GDALCreateScaledProgress().
629 : */
630 :
631 : int CPL_STDCALL GDALScaledProgress( double dfComplete, const char *pszMessage,
632 734 : void *pData )
633 :
634 : {
635 734 : GDALScaledProgressInfo *psInfo = (GDALScaledProgressInfo *) pData;
636 :
637 : return psInfo->pfnProgress( dfComplete * (psInfo->dfMax - psInfo->dfMin)
638 : + psInfo->dfMin,
639 734 : pszMessage, psInfo->pData );
640 : }
641 :
642 : /************************************************************************/
643 : /* GDALCreateScaledProgress() */
644 : /************************************************************************/
645 :
646 : /**
647 : * \brief Create scaled progress transformer.
648 : *
649 : * Sometimes when an operations wants to report progress it actually
650 : * invokes several subprocesses which also take GDALProgressFunc()s,
651 : * and it is desirable to map the progress of each sub operation into
652 : * a portion of 0.0 to 1.0 progress of the overall process. The scaled
653 : * progress function can be used for this.
654 : *
655 : * For each subsection a scaled progress function is created and
656 : * instead of passing the overall progress func down to the sub functions,
657 : * the GDALScaledProgress() function is passed instead.
658 : *
659 : * @param dfMin the value to which 0.0 in the sub operation is mapped.
660 : * @param dfMax the value to which 1.0 is the sub operation is mapped.
661 : * @param pfnProgress the overall progress function.
662 : * @param pData the overall progress function callback data.
663 : *
664 : * @return pointer to pass as pProgressArg to sub functions. Should be freed
665 : * with GDALDestroyScaledProgress().
666 : *
667 : * Example:
668 : *
669 : * \code
670 : * int MyOperation( ..., GDALProgressFunc pfnProgress, void *pProgressData );
671 : *
672 : * {
673 : * void *pScaledProgress;
674 : *
675 : * pScaledProgress = GDALCreateScaledProgress( 0.0, 0.5, pfnProgress,
676 : * pProgressData );
677 : * GDALDoLongSlowOperation( ..., GDALScaledProgress, pScaledProgress );
678 : * GDALDestroyScaledProgress( pScaledProgress );
679 : *
680 : * pScaledProgress = GDALCreateScaledProgress( 0.5, 1.0, pfnProgress,
681 : * pProgressData );
682 : * GDALDoAnotherOperation( ..., GDALScaledProgress, pScaledProgress );
683 : * GDALDestroyScaledProgress( pScaledProgress );
684 : *
685 : * return ...;
686 : * }
687 : * \endcode
688 : */
689 :
690 : void * CPL_STDCALL GDALCreateScaledProgress( double dfMin, double dfMax,
691 : GDALProgressFunc pfnProgress,
692 207 : void * pData )
693 :
694 : {
695 : GDALScaledProgressInfo *psInfo;
696 :
697 : psInfo = (GDALScaledProgressInfo *)
698 207 : CPLCalloc(sizeof(GDALScaledProgressInfo),1);
699 :
700 207 : if( ABS(dfMin-dfMax) < 0.0000001 )
701 0 : dfMax = dfMin + 0.01;
702 :
703 207 : psInfo->pData = pData;
704 207 : psInfo->pfnProgress = pfnProgress;
705 207 : psInfo->dfMin = dfMin;
706 207 : psInfo->dfMax = dfMax;
707 :
708 207 : return (void *) psInfo;
709 : }
710 :
711 : /************************************************************************/
712 : /* GDALDestroyScaledProgress() */
713 : /************************************************************************/
714 :
715 : /**
716 : * \brief Cleanup scaled progress handle.
717 : *
718 : * This function cleans up the data associated with a scaled progress function
719 : * as returned by GADLCreateScaledProgress().
720 : *
721 : * @param pData scaled progress handle returned by GDALCreateScaledProgress().
722 : */
723 :
724 207 : void CPL_STDCALL GDALDestroyScaledProgress( void * pData )
725 :
726 : {
727 207 : CPLFree( pData );
728 207 : }
729 :
730 : /************************************************************************/
731 : /* GDALTermProgress() */
732 : /************************************************************************/
733 :
734 : /**
735 : * \brief Simple progress report to terminal.
736 : *
737 : * This progress reporter prints simple progress report to the
738 : * terminal window. The progress report generally looks something like
739 : * this:
740 :
741 : \verbatim
742 : 0...10...20...30...40...50...60...70...80...90...100 - done.
743 : \endverbatim
744 :
745 : * Every 2.5% of progress another number or period is emitted. Note that
746 : * GDALTermProgress() uses internal static data to keep track of the last
747 : * percentage reported and will get confused if two terminal based progress
748 : * reportings are active at the same time.
749 : *
750 : * The GDALTermProgress() function maintains an internal memory of the
751 : * last percentage complete reported in a static variable, and this makes
752 : * it unsuitable to have multiple GDALTermProgress()'s active eithin a
753 : * single thread or across multiple threads.
754 : *
755 : * @param dfComplete completion ratio from 0.0 to 1.0.
756 : * @param pszMessage optional message.
757 : * @param pProgressArg ignored callback data argument.
758 : *
759 : * @return Always returns TRUE indicating the process should continue.
760 : */
761 :
762 : int CPL_STDCALL GDALTermProgress( double dfComplete, const char *pszMessage,
763 33500 : void * pProgressArg )
764 :
765 : {
766 : static int nLastTick = -1;
767 33500 : int nThisTick = (int) (dfComplete * 40.0);
768 :
769 : (void) pProgressArg;
770 :
771 33500 : nThisTick = MIN(40,MAX(0,nThisTick));
772 :
773 : // Have we started a new progress run?
774 33500 : if( nThisTick < nLastTick && nLastTick >= 39 )
775 13 : nLastTick = -1;
776 :
777 33500 : if( nThisTick <= nLastTick )
778 29917 : return TRUE;
779 :
780 21722 : while( nThisTick > nLastTick )
781 : {
782 14556 : nLastTick++;
783 14556 : if( nLastTick % 4 == 0 )
784 3906 : fprintf( stdout, "%d", (nLastTick / 4) * 10 );
785 : else
786 10650 : fprintf( stdout, "." );
787 : }
788 :
789 3583 : if( nThisTick == 40 )
790 355 : fprintf( stdout, " - done.\n" );
791 : else
792 3228 : fflush( stdout );
793 :
794 3583 : return TRUE;
795 : }
796 :
797 : /************************************************************************/
798 : /* GDALGetRandomRasterSample() */
799 : /************************************************************************/
800 :
801 : int CPL_STDCALL
802 : GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
803 0 : float *pafSampleBuf )
804 :
805 : {
806 0 : VALIDATE_POINTER1( hBand, "GDALGetRandomRasterSample", 0 );
807 :
808 : GDALRasterBand *poBand;
809 :
810 0 : poBand = (GDALRasterBand *) GDALGetRasterSampleOverview( hBand, nSamples );
811 0 : CPLAssert( NULL != poBand );
812 :
813 : /* -------------------------------------------------------------------- */
814 : /* Figure out the ratio of blocks we will read to get an */
815 : /* approximate value. */
816 : /* -------------------------------------------------------------------- */
817 : int nBlockXSize, nBlockYSize;
818 : int nBlocksPerRow, nBlocksPerColumn;
819 : int nSampleRate;
820 : int bGotNoDataValue;
821 : double dfNoDataValue;
822 0 : int nActualSamples = 0;
823 : int nBlockSampleRate;
824 : int nBlockPixels, nBlockCount;
825 :
826 0 : dfNoDataValue = poBand->GetNoDataValue( &bGotNoDataValue );
827 :
828 0 : poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
829 :
830 0 : nBlocksPerRow = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
831 0 : nBlocksPerColumn = (poBand->GetYSize() + nBlockYSize - 1) / nBlockYSize;
832 :
833 0 : nBlockPixels = nBlockXSize * nBlockYSize;
834 0 : nBlockCount = nBlocksPerRow * nBlocksPerColumn;
835 :
836 0 : if( nBlocksPerRow == 0 || nBlocksPerColumn == 0 || nBlockPixels == 0
837 : || nBlockCount == 0 )
838 : {
839 : CPLError( CE_Failure, CPLE_AppDefined,
840 : "GDALGetRandomRasterSample(): returning because band"
841 0 : " appears degenerate." );
842 :
843 0 : return FALSE;
844 : }
845 :
846 0 : nSampleRate = (int) MAX(1,sqrt((double) nBlockCount)-2.0);
847 :
848 0 : if( nSampleRate == nBlocksPerRow && nSampleRate > 1 )
849 0 : nSampleRate--;
850 :
851 0 : while( nSampleRate > 1
852 : && ((nBlockCount-1) / nSampleRate + 1) * nBlockPixels < nSamples )
853 0 : nSampleRate--;
854 :
855 0 : if ((nSamples / ((nBlockCount-1) / nSampleRate + 1)) == 0)
856 0 : nBlockSampleRate = 1;
857 : else
858 : nBlockSampleRate =
859 0 : MAX(1,nBlockPixels / (nSamples / ((nBlockCount-1) / nSampleRate + 1)));
860 :
861 0 : for( int iSampleBlock = 0;
862 : iSampleBlock < nBlockCount;
863 : iSampleBlock += nSampleRate )
864 : {
865 0 : double dfValue = 0.0, dfReal, dfImag;
866 0 : int iXBlock, iYBlock, iX, iY, iXValid, iYValid, iRemainder = 0;
867 : GDALRasterBlock *poBlock;
868 :
869 0 : iYBlock = iSampleBlock / nBlocksPerRow;
870 0 : iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
871 :
872 0 : poBlock = poBand->GetLockedBlockRef( iXBlock, iYBlock );
873 0 : if( poBlock == NULL )
874 0 : continue;
875 0 : if( poBlock->GetDataRef() == NULL )
876 : {
877 0 : poBlock->DropLock();
878 0 : continue;
879 : }
880 :
881 0 : if( (iXBlock + 1) * nBlockXSize > poBand->GetXSize() )
882 0 : iXValid = poBand->GetXSize() - iXBlock * nBlockXSize;
883 : else
884 0 : iXValid = nBlockXSize;
885 :
886 0 : if( (iYBlock + 1) * nBlockYSize > poBand->GetYSize() )
887 0 : iYValid = poBand->GetYSize() - iYBlock * nBlockYSize;
888 : else
889 0 : iYValid = nBlockYSize;
890 :
891 0 : for( iY = 0; iY < iYValid; iY++ )
892 : {
893 0 : for( iX = iRemainder; iX < iXValid; iX += nBlockSampleRate )
894 : {
895 : int iOffset;
896 :
897 0 : iOffset = iX + iY * nBlockXSize;
898 0 : switch( poBlock->GetDataType() )
899 : {
900 : case GDT_Byte:
901 0 : dfValue = ((GByte *) poBlock->GetDataRef())[iOffset];
902 0 : break;
903 : case GDT_UInt16:
904 0 : dfValue = ((GUInt16 *) poBlock->GetDataRef())[iOffset];
905 0 : break;
906 : case GDT_Int16:
907 0 : dfValue = ((GInt16 *) poBlock->GetDataRef())[iOffset];
908 0 : break;
909 : case GDT_UInt32:
910 0 : dfValue = ((GUInt32 *) poBlock->GetDataRef())[iOffset];
911 0 : break;
912 : case GDT_Int32:
913 0 : dfValue = ((GInt32 *) poBlock->GetDataRef())[iOffset];
914 0 : break;
915 : case GDT_Float32:
916 0 : dfValue = ((float *) poBlock->GetDataRef())[iOffset];
917 0 : break;
918 : case GDT_Float64:
919 0 : dfValue = ((double *) poBlock->GetDataRef())[iOffset];
920 0 : break;
921 : case GDT_CInt16:
922 0 : dfReal = ((GInt16 *) poBlock->GetDataRef())[iOffset*2];
923 0 : dfImag = ((GInt16 *) poBlock->GetDataRef())[iOffset*2+1];
924 0 : dfValue = sqrt(dfReal*dfReal + dfImag*dfImag);
925 0 : break;
926 : case GDT_CInt32:
927 0 : dfReal = ((GInt32 *) poBlock->GetDataRef())[iOffset*2];
928 0 : dfImag = ((GInt32 *) poBlock->GetDataRef())[iOffset*2+1];
929 0 : dfValue = sqrt(dfReal*dfReal + dfImag*dfImag);
930 0 : break;
931 : case GDT_CFloat32:
932 0 : dfReal = ((float *) poBlock->GetDataRef())[iOffset*2];
933 0 : dfImag = ((float *) poBlock->GetDataRef())[iOffset*2+1];
934 0 : dfValue = sqrt(dfReal*dfReal + dfImag*dfImag);
935 0 : break;
936 : case GDT_CFloat64:
937 0 : dfReal = ((double *) poBlock->GetDataRef())[iOffset*2];
938 0 : dfImag = ((double *) poBlock->GetDataRef())[iOffset*2+1];
939 0 : dfValue = sqrt(dfReal*dfReal + dfImag*dfImag);
940 0 : break;
941 : default:
942 0 : CPLAssert( FALSE );
943 : }
944 :
945 0 : if( bGotNoDataValue && dfValue == dfNoDataValue )
946 0 : continue;
947 :
948 0 : if( nActualSamples < nSamples )
949 0 : pafSampleBuf[nActualSamples++] = (float) dfValue;
950 : }
951 :
952 0 : iRemainder = iX - iXValid;
953 : }
954 :
955 0 : poBlock->DropLock();
956 : }
957 :
958 0 : return nActualSamples;
959 : }
960 :
961 : /************************************************************************/
962 : /* GDALInitGCPs() */
963 : /************************************************************************/
964 :
965 380 : void CPL_STDCALL GDALInitGCPs( int nCount, GDAL_GCP * psGCP )
966 :
967 : {
968 380 : if( nCount > 0 )
969 : {
970 365 : VALIDATE_POINTER0( psGCP, "GDALInitGCPs" );
971 : }
972 :
973 13629 : for( int iGCP = 0; iGCP < nCount; iGCP++ )
974 : {
975 13249 : memset( psGCP, 0, sizeof(GDAL_GCP) );
976 13249 : psGCP->pszId = CPLStrdup("");
977 13249 : psGCP->pszInfo = CPLStrdup("");
978 13249 : psGCP++;
979 : }
980 : }
981 :
982 : /************************************************************************/
983 : /* GDALDeinitGCPs() */
984 : /************************************************************************/
985 :
986 5944 : void CPL_STDCALL GDALDeinitGCPs( int nCount, GDAL_GCP * psGCP )
987 :
988 : {
989 5944 : if ( nCount > 0 )
990 : {
991 294 : VALIDATE_POINTER0( psGCP, "GDALDeinitGCPs" );
992 : }
993 :
994 19437 : for( int iGCP = 0; iGCP < nCount; iGCP++ )
995 : {
996 13493 : CPLFree( psGCP->pszId );
997 13493 : CPLFree( psGCP->pszInfo );
998 13493 : psGCP++;
999 : }
1000 : }
1001 :
1002 : /************************************************************************/
1003 : /* GDALDuplicateGCPs() */
1004 : /************************************************************************/
1005 :
1006 : GDAL_GCP * CPL_STDCALL
1007 66 : GDALDuplicateGCPs( int nCount, const GDAL_GCP *pasGCPList )
1008 :
1009 : {
1010 : GDAL_GCP *pasReturn;
1011 :
1012 66 : pasReturn = (GDAL_GCP *) CPLMalloc(sizeof(GDAL_GCP) * nCount);
1013 66 : GDALInitGCPs( nCount, pasReturn );
1014 :
1015 330 : for( int iGCP = 0; iGCP < nCount; iGCP++ )
1016 : {
1017 264 : CPLFree( pasReturn[iGCP].pszId );
1018 264 : pasReturn[iGCP].pszId = CPLStrdup( pasGCPList[iGCP].pszId );
1019 :
1020 264 : CPLFree( pasReturn[iGCP].pszInfo );
1021 264 : pasReturn[iGCP].pszInfo = CPLStrdup( pasGCPList[iGCP].pszInfo );
1022 :
1023 264 : pasReturn[iGCP].dfGCPPixel = pasGCPList[iGCP].dfGCPPixel;
1024 264 : pasReturn[iGCP].dfGCPLine = pasGCPList[iGCP].dfGCPLine;
1025 264 : pasReturn[iGCP].dfGCPX = pasGCPList[iGCP].dfGCPX;
1026 264 : pasReturn[iGCP].dfGCPY = pasGCPList[iGCP].dfGCPY;
1027 264 : pasReturn[iGCP].dfGCPZ = pasGCPList[iGCP].dfGCPZ;
1028 : }
1029 :
1030 66 : return pasReturn;
1031 : }
1032 :
1033 : /************************************************************************/
1034 : /* GDALLoadOziMapFile() */
1035 : /************************************************************************/
1036 :
1037 : #define MAX_GCP 30
1038 :
1039 : int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
1040 : double *padfGeoTransform, char **ppszWKT,
1041 0 : int *pnGCPCount, GDAL_GCP **ppasGCPs )
1042 :
1043 :
1044 : {
1045 : char **papszLines;
1046 0 : int iLine, nLines=0;
1047 0 : int nCoordinateCount = 0;
1048 : GDAL_GCP asGCPs[MAX_GCP];
1049 :
1050 0 : VALIDATE_POINTER1( pszFilename, "GDALLoadOziMapFile", FALSE );
1051 0 : VALIDATE_POINTER1( padfGeoTransform, "GDALLoadOziMapFile", FALSE );
1052 0 : VALIDATE_POINTER1( pnGCPCount, "GDALLoadOziMapFile", FALSE );
1053 0 : VALIDATE_POINTER1( ppasGCPs, "GDALLoadOziMapFile", FALSE );
1054 :
1055 0 : papszLines = CSLLoad2( pszFilename, 1000, 200, NULL );
1056 :
1057 0 : if ( !papszLines )
1058 0 : return FALSE;
1059 :
1060 0 : nLines = CSLCount( papszLines );
1061 :
1062 : // Check the OziExplorer Map file signature
1063 0 : if ( nLines < 5
1064 : || !EQUALN(papszLines[0], "OziExplorer Map Data File Version ", 34) )
1065 : {
1066 : CPLError( CE_Failure, CPLE_AppDefined,
1067 : "GDALLoadOziMapFile(): file \"%s\" is not in OziExplorer Map format.",
1068 0 : pszFilename );
1069 0 : CSLDestroy( papszLines );
1070 0 : return FALSE;
1071 : }
1072 :
1073 0 : OGRSpatialReference oSRS;
1074 0 : const char *pszProj = NULL, *pszProjParms = NULL;
1075 0 : OGRErr eErr = OGRERR_NONE;
1076 :
1077 0 : for ( iLine = 5; iLine < nLines; iLine++ )
1078 : {
1079 0 : if ( EQUALN(papszLines[iLine], "Map Projection", 14) )
1080 : {
1081 0 : pszProj = papszLines[iLine];
1082 0 : continue;
1083 : }
1084 :
1085 0 : if ( EQUALN(papszLines[iLine], "Projection Setup", 16) )
1086 : {
1087 0 : pszProjParms = papszLines[iLine];
1088 0 : continue;
1089 : }
1090 : }
1091 :
1092 0 : if ( papszLines[4][0] != '\0' && pszProj && pszProjParms )
1093 : {
1094 0 : eErr = oSRS.importFromOzi( papszLines[4], pszProj, pszProjParms );
1095 0 : if ( eErr == OGRERR_NONE )
1096 : {
1097 0 : if ( ppszWKT != NULL )
1098 0 : oSRS.exportToWkt( ppszWKT );
1099 : }
1100 : }
1101 :
1102 : // Iterate all lines in the TAB-file
1103 0 : for ( iLine = 5; iLine < nLines; iLine++ )
1104 : {
1105 0 : char **papszTok = NULL;
1106 :
1107 : papszTok = CSLTokenizeString2( papszLines[iLine], ",",
1108 : CSLT_ALLOWEMPTYTOKENS
1109 : | CSLT_STRIPLEADSPACES
1110 0 : | CSLT_STRIPENDSPACES );
1111 :
1112 0 : if ( CSLCount(papszTok) < 12 )
1113 0 : continue;
1114 :
1115 0 : if ( CSLCount(papszTok) >= 17
1116 : && EQUALN(papszTok[0], "Point", 5)
1117 : && !EQUAL(papszTok[2], "")
1118 : && !EQUAL(papszTok[3], "")
1119 : && nCoordinateCount < MAX_GCP )
1120 : {
1121 0 : int bReadOk = FALSE;
1122 : double dfLon, dfLat;
1123 :
1124 0 : if ( !EQUAL(papszTok[6], "")
1125 : && !EQUAL(papszTok[7], "")
1126 : && !EQUAL(papszTok[9], "")
1127 : && !EQUAL(papszTok[10], "") )
1128 : {
1129 : // Set geographical coordinates of the pixels
1130 0 : dfLon = CPLAtofM(papszTok[9]) + CPLAtofM(papszTok[10]) / 60.0;
1131 0 : dfLat = CPLAtofM(papszTok[6]) + CPLAtofM(papszTok[7]) / 60.0;
1132 0 : if ( EQUAL(papszTok[11], "W") )
1133 0 : dfLon = -dfLon;
1134 0 : if ( EQUAL(papszTok[8], "S") )
1135 0 : dfLat = -dfLat;
1136 :
1137 : // Transform from the geographical coordinates into projected
1138 : // coordinates.
1139 0 : if ( eErr == OGRERR_NONE )
1140 : {
1141 0 : OGRSpatialReference *poLatLong = NULL;
1142 0 : OGRCoordinateTransformation *poTransform = NULL;
1143 :
1144 0 : poLatLong = oSRS.CloneGeogCS();
1145 0 : if ( poLatLong )
1146 : {
1147 0 : poTransform = OGRCreateCoordinateTransformation( poLatLong, &oSRS );
1148 0 : if ( poTransform )
1149 : {
1150 0 : bReadOk = poTransform->Transform( 1, &dfLon, &dfLat );
1151 0 : delete poTransform;
1152 : }
1153 0 : delete poLatLong;
1154 : }
1155 : }
1156 : }
1157 0 : else if ( !EQUAL(papszTok[14], "")
1158 : && !EQUAL(papszTok[15], "") )
1159 : {
1160 : // Set cartesian coordinates of the pixels.
1161 0 : dfLon = CPLAtofM(papszTok[14]);
1162 0 : dfLat = CPLAtofM(papszTok[15]);
1163 0 : bReadOk = TRUE;
1164 :
1165 0 : if ( EQUAL(papszTok[16], "S") )
1166 0 : dfLat = -dfLat;
1167 : }
1168 :
1169 0 : if ( bReadOk )
1170 : {
1171 0 : GDALInitGCPs( 1, asGCPs + nCoordinateCount );
1172 :
1173 : // Set pixel/line part
1174 0 : asGCPs[nCoordinateCount].dfGCPPixel = CPLAtofM(papszTok[2]);
1175 0 : asGCPs[nCoordinateCount].dfGCPLine = CPLAtofM(papszTok[3]);
1176 :
1177 0 : asGCPs[nCoordinateCount].dfGCPX = dfLon;
1178 0 : asGCPs[nCoordinateCount].dfGCPY = dfLat;
1179 :
1180 0 : nCoordinateCount++;
1181 : }
1182 : }
1183 :
1184 0 : CSLDestroy( papszTok );
1185 : }
1186 :
1187 0 : CSLDestroy( papszLines );
1188 :
1189 0 : if ( nCoordinateCount == 0 )
1190 : {
1191 : CPLDebug( "GDAL", "GDALLoadOziMapFile(\"%s\") did read no GCPs.",
1192 0 : pszFilename );
1193 0 : return FALSE;
1194 : }
1195 :
1196 : /* -------------------------------------------------------------------- */
1197 : /* Try to convert the GCPs into a geotransform definition, if */
1198 : /* possible. Otherwise we will need to use them as GCPs. */
1199 : /* -------------------------------------------------------------------- */
1200 0 : if( !GDALGCPsToGeoTransform( nCoordinateCount, asGCPs, padfGeoTransform,
1201 : FALSE ) )
1202 : {
1203 0 : if ( pnGCPCount && ppasGCPs )
1204 : {
1205 : CPLDebug( "GDAL",
1206 : "GDALLoadOziMapFile(%s) found file, wasn't able to derive a\n"
1207 : "first order geotransform. Using points as GCPs.",
1208 0 : pszFilename );
1209 :
1210 : *ppasGCPs = (GDAL_GCP *)
1211 0 : CPLCalloc( sizeof(GDAL_GCP),nCoordinateCount );
1212 0 : memcpy( *ppasGCPs, asGCPs, sizeof(GDAL_GCP) * nCoordinateCount );
1213 0 : *pnGCPCount = nCoordinateCount;
1214 : }
1215 : }
1216 : else
1217 : {
1218 0 : GDALDeinitGCPs( nCoordinateCount, asGCPs );
1219 : }
1220 :
1221 0 : return TRUE;
1222 : }
1223 :
1224 : #undef MAX_GCP
1225 :
1226 : /************************************************************************/
1227 : /* GDALReadOziMapFile() */
1228 : /************************************************************************/
1229 :
1230 : int CPL_STDCALL GDALReadOziMapFile( const char * pszBaseFilename,
1231 : double *padfGeoTransform, char **ppszWKT,
1232 25 : int *pnGCPCount, GDAL_GCP **ppasGCPs )
1233 :
1234 :
1235 : {
1236 : const char *pszOzi;
1237 : FILE *fpOzi;
1238 :
1239 : /* -------------------------------------------------------------------- */
1240 : /* Try lower case, then upper case. */
1241 : /* -------------------------------------------------------------------- */
1242 25 : pszOzi = CPLResetExtension( pszBaseFilename, "map" );
1243 :
1244 25 : fpOzi = VSIFOpen( pszOzi, "rt" );
1245 :
1246 : #ifndef WIN32
1247 25 : if ( fpOzi == NULL )
1248 : {
1249 25 : pszOzi = CPLResetExtension( pszBaseFilename, "MAP" );
1250 25 : fpOzi = VSIFOpen( pszOzi, "rt" );
1251 : }
1252 : #endif
1253 :
1254 25 : if ( fpOzi == NULL )
1255 25 : return FALSE;
1256 :
1257 0 : VSIFClose( fpOzi );
1258 :
1259 : /* -------------------------------------------------------------------- */
1260 : /* We found the file, now load and parse it. */
1261 : /* -------------------------------------------------------------------- */
1262 : return GDALLoadOziMapFile( pszOzi, padfGeoTransform, ppszWKT,
1263 0 : pnGCPCount, ppasGCPs );
1264 : }
1265 :
1266 : /************************************************************************/
1267 : /* GDALLoadTabFile() */
1268 : /* */
1269 : /* Helper function for translator implementators wanting */
1270 : /* support for MapInfo .tab-files. */
1271 : /************************************************************************/
1272 :
1273 : #define MAX_GCP 256
1274 :
1275 : int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
1276 : double *padfGeoTransform, char **ppszWKT,
1277 2 : int *pnGCPCount, GDAL_GCP **ppasGCPs )
1278 :
1279 :
1280 : {
1281 : char **papszLines;
1282 2 : char **papszTok=NULL;
1283 2 : int bTypeRasterFound = FALSE;
1284 2 : int bInsideTableDef = FALSE;
1285 2 : int iLine, numLines=0;
1286 2 : int nCoordinateCount = 0;
1287 : GDAL_GCP asGCPs[MAX_GCP];
1288 :
1289 2 : papszLines = CSLLoad2( pszFilename, 1000, 200, NULL );
1290 :
1291 2 : if ( !papszLines )
1292 0 : return FALSE;
1293 :
1294 2 : numLines = CSLCount(papszLines);
1295 :
1296 : // Iterate all lines in the TAB-file
1297 28 : for(iLine=0; iLine<numLines; iLine++)
1298 : {
1299 26 : CSLDestroy(papszTok);
1300 : papszTok = CSLTokenizeStringComplex(papszLines[iLine], " \t(),;",
1301 26 : TRUE, FALSE);
1302 :
1303 26 : if (CSLCount(papszTok) < 2)
1304 4 : continue;
1305 :
1306 : // Did we find table definition
1307 24 : if (EQUAL(papszTok[0], "Definition") && EQUAL(papszTok[1], "Table") )
1308 : {
1309 2 : bInsideTableDef = TRUE;
1310 : }
1311 22 : else if (bInsideTableDef && (EQUAL(papszTok[0], "Type")) )
1312 : {
1313 : // Only RASTER-type will be handled
1314 2 : if (EQUAL(papszTok[1], "RASTER"))
1315 : {
1316 2 : bTypeRasterFound = TRUE;
1317 : }
1318 : else
1319 : {
1320 0 : CSLDestroy(papszTok);
1321 0 : CSLDestroy(papszLines);
1322 0 : return FALSE;
1323 : }
1324 : }
1325 18 : else if (bTypeRasterFound && bInsideTableDef
1326 : && CSLCount(papszTok) > 4
1327 : && EQUAL(papszTok[4], "Label")
1328 : && nCoordinateCount < MAX_GCP )
1329 : {
1330 8 : GDALInitGCPs( 1, asGCPs + nCoordinateCount );
1331 :
1332 8 : asGCPs[nCoordinateCount].dfGCPPixel = CPLAtofM(papszTok[2]);
1333 8 : asGCPs[nCoordinateCount].dfGCPLine = CPLAtofM(papszTok[3]);
1334 8 : asGCPs[nCoordinateCount].dfGCPX = CPLAtofM(papszTok[0]);
1335 8 : asGCPs[nCoordinateCount].dfGCPY = CPLAtofM(papszTok[1]);
1336 8 : if( papszTok[5] != NULL )
1337 : {
1338 8 : CPLFree( asGCPs[nCoordinateCount].pszId );
1339 8 : asGCPs[nCoordinateCount].pszId = CPLStrdup(papszTok[5]);
1340 : }
1341 :
1342 8 : nCoordinateCount++;
1343 : }
1344 12 : else if( bTypeRasterFound && bInsideTableDef
1345 : && EQUAL(papszTok[0],"CoordSys")
1346 : && ppszWKT != NULL )
1347 : {
1348 2 : OGRSpatialReference oSRS;
1349 :
1350 2 : if( oSRS.importFromMICoordSys( papszLines[iLine] ) == OGRERR_NONE )
1351 2 : oSRS.exportToWkt( ppszWKT );
1352 : }
1353 8 : else if( EQUAL(papszTok[0],"Units")
1354 : && CSLCount(papszTok) > 1
1355 : && EQUAL(papszTok[1],"degree") )
1356 : {
1357 : /*
1358 : ** If we have units of "degree", but a projected coordinate
1359 : ** system we need to convert it to geographic. See to01_02.TAB.
1360 : */
1361 0 : if( ppszWKT != NULL && *ppszWKT != NULL
1362 : && EQUALN(*ppszWKT,"PROJCS",6) )
1363 : {
1364 0 : OGRSpatialReference oSRS, oSRSGeogCS;
1365 0 : char *pszSrcWKT = *ppszWKT;
1366 :
1367 0 : oSRS.importFromWkt( &pszSrcWKT );
1368 0 : oSRSGeogCS.CopyGeogCSFrom( &oSRS );
1369 0 : CPLFree( *ppszWKT );
1370 0 : oSRSGeogCS.exportToWkt( ppszWKT );
1371 : }
1372 : }
1373 :
1374 : }
1375 :
1376 2 : CSLDestroy(papszTok);
1377 2 : CSLDestroy(papszLines);
1378 :
1379 2 : if( nCoordinateCount == 0 )
1380 : {
1381 : CPLDebug( "GDAL", "GDALLoadTabFile(%s) did not get any GCPs.",
1382 0 : pszFilename );
1383 0 : return FALSE;
1384 : }
1385 :
1386 : /* -------------------------------------------------------------------- */
1387 : /* Try to convert the GCPs into a geotransform definition, if */
1388 : /* possible. Otherwise we will need to use them as GCPs. */
1389 : /* -------------------------------------------------------------------- */
1390 2 : if( !GDALGCPsToGeoTransform( nCoordinateCount, asGCPs, padfGeoTransform,
1391 : FALSE ) )
1392 : {
1393 0 : if (pnGCPCount && ppasGCPs)
1394 : {
1395 : CPLDebug( "GDAL",
1396 : "GDALLoadTabFile(%s) found file, wasn't able to derive a\n"
1397 : "first order geotransform. Using points as GCPs.",
1398 0 : pszFilename );
1399 :
1400 : *ppasGCPs = (GDAL_GCP *)
1401 0 : CPLCalloc( sizeof(GDAL_GCP),nCoordinateCount );
1402 0 : memcpy( *ppasGCPs, asGCPs, sizeof(GDAL_GCP) * nCoordinateCount );
1403 0 : *pnGCPCount = nCoordinateCount;
1404 : }
1405 : }
1406 : else
1407 : {
1408 2 : GDALDeinitGCPs( nCoordinateCount, asGCPs );
1409 : }
1410 :
1411 2 : return TRUE;
1412 : }
1413 :
1414 : #undef MAX_GCP
1415 :
1416 : /************************************************************************/
1417 : /* GDALReadTabFile() */
1418 : /* */
1419 : /* Helper function for translator implementators wanting */
1420 : /* support for MapInfo .tab-files. */
1421 : /************************************************************************/
1422 :
1423 : int CPL_STDCALL GDALReadTabFile( const char * pszBaseFilename,
1424 : double *padfGeoTransform, char **ppszWKT,
1425 945 : int *pnGCPCount, GDAL_GCP **ppasGCPs )
1426 :
1427 :
1428 : {
1429 : const char *pszTAB;
1430 : FILE *fpTAB;
1431 :
1432 : /* -------------------------------------------------------------------- */
1433 : /* Try lower case, then upper case. */
1434 : /* -------------------------------------------------------------------- */
1435 945 : pszTAB = CPLResetExtension( pszBaseFilename, "tab" );
1436 :
1437 945 : fpTAB = VSIFOpenL( pszTAB, "rt" );
1438 :
1439 : #ifndef WIN32
1440 945 : if( fpTAB == NULL )
1441 : {
1442 943 : pszTAB = CPLResetExtension( pszBaseFilename, "TAB" );
1443 943 : fpTAB = VSIFOpenL( pszTAB, "rt" );
1444 : }
1445 : #endif
1446 :
1447 945 : if( fpTAB == NULL )
1448 943 : return FALSE;
1449 :
1450 2 : VSIFCloseL( fpTAB );
1451 :
1452 : /* -------------------------------------------------------------------- */
1453 : /* We found the file, now load and parse it. */
1454 : /* -------------------------------------------------------------------- */
1455 : return GDALLoadTabFile( pszTAB, padfGeoTransform, ppszWKT,
1456 2 : pnGCPCount, ppasGCPs );
1457 : }
1458 :
1459 : /************************************************************************/
1460 : /* GDALLoadWorldFile() */
1461 : /************************************************************************/
1462 :
1463 : /**
1464 : * \brief Read ESRI world file.
1465 : *
1466 : * This function reads an ESRI style world file, and formats a geotransform
1467 : * from its contents.
1468 : *
1469 : * The world file contains an affine transformation with the parameters
1470 : * in a different order than in a geotransform array.
1471 : *
1472 : * <ul>
1473 : * <li> geotransform[1] : width of pixel
1474 : * <li> geotransform[4] : rotational coefficient, zero for north up images.
1475 : * <li> geotransform[2] : rotational coefficient, zero for north up images.
1476 : * <li> geotransform[5] : height of pixel (but negative)
1477 : * <li> geotransform[0] + 0.5 * geotransform[1] + 0.5 * geotransform[2] : x offset to center of top left pixel.
1478 : * <li> geotransform[3] + 0.5 * geotransform[4] + 0.5 * geotransform[5] : y offset to center of top left pixel.
1479 : * </ul>
1480 : *
1481 : * @param pszFilename the world file name.
1482 : * @param padfGeoTransform the six double array into which the
1483 : * geotransformation should be placed.
1484 : *
1485 : * @return TRUE on success or FALSE on failure.
1486 : */
1487 :
1488 : int CPL_STDCALL
1489 16 : GDALLoadWorldFile( const char *pszFilename, double *padfGeoTransform )
1490 :
1491 : {
1492 : char **papszLines;
1493 :
1494 16 : VALIDATE_POINTER1( pszFilename, "GDALLoadWorldFile", FALSE );
1495 16 : VALIDATE_POINTER1( padfGeoTransform, "GDALLoadWorldFile", FALSE );
1496 :
1497 16 : papszLines = CSLLoad2( pszFilename, 100, 100, NULL );
1498 :
1499 16 : if ( !papszLines )
1500 0 : return FALSE;
1501 :
1502 : double world[6];
1503 : // reads the first 6 non-empty lines
1504 16 : int nLines = 0;
1505 16 : int nLinesCount = CSLCount(papszLines);
1506 112 : for( int i = 0; i < nLinesCount && nLines < 6; ++i )
1507 : {
1508 96 : CPLString line(papszLines[i]);
1509 96 : if( line.Trim().empty() )
1510 0 : continue;
1511 :
1512 96 : world[nLines] = CPLAtofM(line);
1513 96 : ++nLines;
1514 : }
1515 :
1516 16 : if( nLines == 6
1517 : && (world[0] != 0.0 || world[2] != 0.0)
1518 : && (world[3] != 0.0 || world[1] != 0.0) )
1519 : {
1520 16 : padfGeoTransform[0] = world[4];
1521 16 : padfGeoTransform[1] = world[0];
1522 16 : padfGeoTransform[2] = world[2];
1523 16 : padfGeoTransform[3] = world[5];
1524 16 : padfGeoTransform[4] = world[1];
1525 16 : padfGeoTransform[5] = world[3];
1526 :
1527 : // correct for center of pixel vs. top left of pixel
1528 16 : padfGeoTransform[0] -= 0.5 * padfGeoTransform[1];
1529 16 : padfGeoTransform[0] -= 0.5 * padfGeoTransform[2];
1530 16 : padfGeoTransform[3] -= 0.5 * padfGeoTransform[4];
1531 16 : padfGeoTransform[3] -= 0.5 * padfGeoTransform[5];
1532 :
1533 16 : CSLDestroy(papszLines);
1534 :
1535 16 : return TRUE;
1536 : }
1537 : else
1538 : {
1539 : CPLDebug( "GDAL",
1540 : "GDALLoadWorldFile(%s) found file, but it was corrupt.",
1541 0 : pszFilename );
1542 0 : CSLDestroy(papszLines);
1543 0 : return FALSE;
1544 : }
1545 : }
1546 :
1547 : /************************************************************************/
1548 : /* GDALReadWorldFile() */
1549 : /************************************************************************/
1550 :
1551 : /**
1552 : * \brief Read ESRI world file.
1553 : *
1554 : * This function reads an ESRI style world file, and formats a geotransform
1555 : * from its contents. It does the same as GDALLoadWorldFile() function, but
1556 : * it will form the filename for the worldfile from the filename of the raster
1557 : * file referred and the suggested extension. If no extension is provided,
1558 : * the code will internally try the unix style and windows style world file
1559 : * extensions (eg. for .tif these would be .tfw and .tifw).
1560 : *
1561 : * The world file contains an affine transformation with the parameters
1562 : * in a different order than in a geotransform array.
1563 : *
1564 : * <ul>
1565 : * <li> geotransform[1] : width of pixel
1566 : * <li> geotransform[4] : rotational coefficient, zero for north up images.
1567 : * <li> geotransform[2] : rotational coefficient, zero for north up images.
1568 : * <li> geotransform[5] : height of pixel (but negative)
1569 : * <li> geotransform[0] + 0.5 * geotransform[1] + 0.5 * geotransform[2] : x offset to center of top left pixel.
1570 : * <li> geotransform[3] + 0.5 * geotransform[4] + 0.5 * geotransform[5] : y offset to center of top left pixel.
1571 : * </ul>
1572 : *
1573 : * @param pszBaseFilename the target raster file.
1574 : * @param pszExtension the extension to use (ie. ".wld") or NULL to derive it
1575 : * from the pszBaseFilename
1576 : * @param padfGeoTransform the six double array into which the
1577 : * geotransformation should be placed.
1578 : *
1579 : * @return TRUE on success or FALSE on failure.
1580 : */
1581 :
1582 : int CPL_STDCALL
1583 : GDALReadWorldFile( const char *pszBaseFilename, const char *pszExtension,
1584 4993 : double *padfGeoTransform )
1585 :
1586 : {
1587 : const char *pszTFW;
1588 : char szExtUpper[32], szExtLower[32];
1589 : int i;
1590 :
1591 4993 : VALIDATE_POINTER1( pszBaseFilename, "GDALReadWorldFile", FALSE );
1592 4993 : VALIDATE_POINTER1( padfGeoTransform, "GDALReadWorldFile", FALSE );
1593 :
1594 : /* -------------------------------------------------------------------- */
1595 : /* If we aren't given an extension, try both the unix and */
1596 : /* windows style extensions. */
1597 : /* -------------------------------------------------------------------- */
1598 4993 : if( pszExtension == NULL )
1599 : {
1600 : char szDerivedExtension[100];
1601 1148 : std::string oBaseExt = CPLGetExtension( pszBaseFilename );
1602 :
1603 2296 : if( oBaseExt.length() < 2 )
1604 1267 : return FALSE;
1605 :
1606 : // windows version - first + last + 'w'
1607 1029 : szDerivedExtension[0] = oBaseExt[0];
1608 1029 : szDerivedExtension[1] = oBaseExt[oBaseExt.length()-1];
1609 1029 : szDerivedExtension[2] = 'w';
1610 1029 : szDerivedExtension[3] = '\0';
1611 :
1612 1029 : if( GDALReadWorldFile( pszBaseFilename, szDerivedExtension,
1613 : padfGeoTransform ) )
1614 5 : return TRUE;
1615 :
1616 : // unix version - extension + 'w'
1617 1024 : if( oBaseExt.length() > sizeof(szDerivedExtension)-2 )
1618 0 : return FALSE;
1619 :
1620 1024 : strcpy( szDerivedExtension, oBaseExt.c_str() );
1621 1024 : strcat( szDerivedExtension, "w" );
1622 : return GDALReadWorldFile( pszBaseFilename, szDerivedExtension,
1623 1024 : padfGeoTransform );
1624 : }
1625 :
1626 : /* -------------------------------------------------------------------- */
1627 : /* Skip the leading period in the extension if there is one. */
1628 : /* -------------------------------------------------------------------- */
1629 3845 : if( *pszExtension == '.' )
1630 334 : pszExtension++;
1631 :
1632 : /* -------------------------------------------------------------------- */
1633 : /* Generate upper and lower case versions of the extension. */
1634 : /* -------------------------------------------------------------------- */
1635 3845 : CPLStrlcpy( szExtUpper, pszExtension, sizeof(szExtUpper) );
1636 3845 : CPLStrlcpy( szExtLower, pszExtension, sizeof(szExtLower) );
1637 :
1638 16451 : for( i = 0; szExtUpper[i] != '\0'; i++ )
1639 : {
1640 12606 : szExtUpper[i] = (char) toupper(szExtUpper[i]);
1641 12606 : szExtLower[i] = (char) tolower(szExtLower[i]);
1642 : }
1643 :
1644 : /* -------------------------------------------------------------------- */
1645 : /* Try lower case, then upper case. */
1646 : /* -------------------------------------------------------------------- */
1647 : VSIStatBufL sStatBuf;
1648 : int bGotTFW;
1649 :
1650 3845 : pszTFW = CPLResetExtension( pszBaseFilename, szExtLower );
1651 :
1652 3845 : bGotTFW = VSIStatL( pszTFW, &sStatBuf ) == 0;
1653 :
1654 : #ifndef WIN32
1655 3845 : if( !bGotTFW )
1656 : {
1657 3829 : pszTFW = CPLResetExtension( pszBaseFilename, szExtUpper );
1658 3829 : bGotTFW = VSIStatL( pszTFW, &sStatBuf ) == 0;
1659 : }
1660 : #endif
1661 :
1662 3845 : if( !bGotTFW )
1663 3829 : return FALSE;
1664 :
1665 : /* -------------------------------------------------------------------- */
1666 : /* We found the file, now load and parse it. */
1667 : /* -------------------------------------------------------------------- */
1668 16 : return GDALLoadWorldFile( pszTFW, padfGeoTransform );
1669 : }
1670 :
1671 : /************************************************************************/
1672 : /* GDALWriteWorldFile() */
1673 : /* */
1674 : /* Helper function for translator implementators wanting */
1675 : /* support for ESRI world files. */
1676 : /************************************************************************/
1677 :
1678 : /**
1679 : * \brief Write ESRI world file.
1680 : *
1681 : * This function writes an ESRI style world file from the passed geotransform.
1682 : *
1683 : * The world file contains an affine transformation with the parameters
1684 : * in a different order than in a geotransform array.
1685 : *
1686 : * <ul>
1687 : * <li> geotransform[1] : width of pixel
1688 : * <li> geotransform[4] : rotational coefficient, zero for north up images.
1689 : * <li> geotransform[2] : rotational coefficient, zero for north up images.
1690 : * <li> geotransform[5] : height of pixel (but negative)
1691 : * <li> geotransform[0] + 0.5 * geotransform[1] + 0.5 * geotransform[2] : x offset to center of top left pixel.
1692 : * <li> geotransform[3] + 0.5 * geotransform[4] + 0.5 * geotransform[5] : y offset to center of top left pixel.
1693 : * </ul>
1694 : *
1695 : * @param pszBaseFilename the target raster file.
1696 : * @param pszExtension the extension to use (ie. ".wld"). Must not be NULL
1697 : * @param padfGeoTransform the six double array from which the
1698 : * geotransformation should be read.
1699 : *
1700 : * @return TRUE on success or FALSE on failure.
1701 : */
1702 :
1703 : int CPL_STDCALL
1704 : GDALWriteWorldFile( const char * pszBaseFilename, const char *pszExtension,
1705 6 : double *padfGeoTransform )
1706 :
1707 : {
1708 6 : VALIDATE_POINTER1( pszBaseFilename, "GDALWriteWorldFile", FALSE );
1709 6 : VALIDATE_POINTER1( pszExtension, "GDALWriteWorldFile", FALSE );
1710 6 : VALIDATE_POINTER1( padfGeoTransform, "GDALWriteWorldFile", FALSE );
1711 :
1712 : /* -------------------------------------------------------------------- */
1713 : /* Prepare the text to write to the file. */
1714 : /* -------------------------------------------------------------------- */
1715 6 : CPLString osTFWText;
1716 :
1717 : osTFWText.Printf( "%.10f\n%.10f\n%.10f\n%.10f\n%.10f\n%.10f\n",
1718 : padfGeoTransform[1],
1719 : padfGeoTransform[4],
1720 : padfGeoTransform[2],
1721 : padfGeoTransform[5],
1722 : padfGeoTransform[0]
1723 : + 0.5 * padfGeoTransform[1]
1724 : + 0.5 * padfGeoTransform[2],
1725 : padfGeoTransform[3]
1726 : + 0.5 * padfGeoTransform[4]
1727 6 : + 0.5 * padfGeoTransform[5] );
1728 :
1729 : /* -------------------------------------------------------------------- */
1730 : /* Update extention, and write to disk. */
1731 : /* -------------------------------------------------------------------- */
1732 : const char *pszTFW;
1733 : FILE *fpTFW;
1734 :
1735 6 : pszTFW = CPLResetExtension( pszBaseFilename, pszExtension );
1736 6 : fpTFW = VSIFOpenL( pszTFW, "wt" );
1737 6 : if( fpTFW == NULL )
1738 6 : return FALSE;
1739 :
1740 6 : VSIFWriteL( (void *) osTFWText.c_str(), 1, osTFWText.size(), fpTFW );
1741 6 : VSIFCloseL( fpTFW );
1742 :
1743 6 : return TRUE;
1744 : }
1745 :
1746 : /************************************************************************/
1747 : /* GDALVersionInfo() */
1748 : /************************************************************************/
1749 :
1750 : /**
1751 : * \brief Get runtime version information.
1752 : *
1753 : * Available pszRequest values:
1754 : * <ul>
1755 : * <li> "VERSION_NUM": Returns GDAL_VERSION_NUM formatted as a string. ie. "1170"
1756 : * <li> "RELEASE_DATE": Returns GDAL_RELEASE_DATE formatted as a string.
1757 : * ie. "20020416".
1758 : * <li> "RELEASE_NAME": Returns the GDAL_RELEASE_NAME. ie. "1.1.7"
1759 : * <li> "--version": Returns one line version message suitable for use in
1760 : * response to --version requests. ie. "GDAL 1.1.7, released 2002/04/16"
1761 : * <li> "LICENCE": Returns the content of the LICENSE.TXT file from the GDAL_DATA directory.
1762 : * Before GDAL 1.7.0, the returned string was leaking memory but this is now resolved.
1763 : * So the result should not been freed by the caller.
1764 : * </ul>
1765 : *
1766 : * @param pszRequest the type of version info desired, as listed above.
1767 : *
1768 : * @return an internal string containing the requested information.
1769 : */
1770 :
1771 343 : const char * CPL_STDCALL GDALVersionInfo( const char *pszRequest )
1772 :
1773 : {
1774 : /* -------------------------------------------------------------------- */
1775 : /* LICENSE is a special case. We try to find and read the */
1776 : /* LICENSE.TXT file from the GDAL_DATA directory and return it */
1777 : /* -------------------------------------------------------------------- */
1778 343 : if( pszRequest != NULL && EQUAL(pszRequest,"LICENSE") )
1779 : {
1780 0 : char* pszResultLicence = (char*) CPLGetTLS( CTLS_VERSIONINFO_LICENCE );
1781 0 : if( pszResultLicence != NULL )
1782 : {
1783 0 : return pszResultLicence;
1784 : }
1785 :
1786 0 : const char *pszFilename = CPLFindFile( "etc", "LICENSE.TXT" );
1787 0 : FILE *fp = NULL;
1788 : int nLength;
1789 :
1790 0 : if( pszFilename != NULL )
1791 0 : fp = VSIFOpenL( pszFilename, "r" );
1792 :
1793 0 : if( fp != NULL )
1794 : {
1795 0 : VSIFSeekL( fp, 0, SEEK_END );
1796 0 : nLength = (int) VSIFTellL( fp ) + 1;
1797 0 : VSIFSeekL( fp, SEEK_SET, 0 );
1798 :
1799 0 : pszResultLicence = (char *) VSICalloc(1,nLength);
1800 0 : if (pszResultLicence)
1801 0 : VSIFReadL( pszResultLicence, 1, nLength-1, fp );
1802 :
1803 0 : VSIFCloseL( fp );
1804 : }
1805 :
1806 0 : if (!pszResultLicence)
1807 : {
1808 : pszResultLicence = CPLStrdup(
1809 : "GDAL/OGR is released under the MIT/X license.\n"
1810 : "The LICENSE.TXT distributed with GDAL/OGR should\n"
1811 0 : "contain additional details.\n" );
1812 : }
1813 :
1814 0 : CPLSetTLS( CTLS_VERSIONINFO_LICENCE, pszResultLicence, TRUE );
1815 0 : return pszResultLicence;
1816 : }
1817 :
1818 343 : char* pszResultSmall = (char*) CPLGetTLS( CTLS_VERSIONINFO );
1819 343 : if( pszResultSmall == NULL )
1820 : {
1821 324 : pszResultSmall = (char*) CPLCalloc(128, 1);
1822 324 : CPLSetTLS( CTLS_VERSIONINFO, pszResultSmall, TRUE );
1823 : }
1824 :
1825 669 : if( pszRequest == NULL || EQUAL(pszRequest,"VERSION_NUM") )
1826 326 : sprintf(pszResultSmall, "%d", GDAL_VERSION_NUM );
1827 17 : else if( EQUAL(pszRequest,"RELEASE_DATE") )
1828 0 : sprintf(pszResultSmall, "%d", GDAL_RELEASE_DATE );
1829 17 : else if( EQUAL(pszRequest,"RELEASE_NAME") )
1830 17 : sprintf(pszResultSmall, GDAL_RELEASE_NAME );
1831 : else // --version
1832 : sprintf(pszResultSmall, "GDAL %s, released %d/%02d/%02d",
1833 : GDAL_RELEASE_NAME,
1834 : GDAL_RELEASE_DATE / 10000,
1835 : (GDAL_RELEASE_DATE % 10000) / 100,
1836 0 : GDAL_RELEASE_DATE % 100 );
1837 :
1838 343 : return pszResultSmall;
1839 : }
1840 :
1841 : /************************************************************************/
1842 : /* GDALCheckVersion() */
1843 : /************************************************************************/
1844 :
1845 : /** Return TRUE if GDAL library version at runtime matches nVersionMajor.nVersionMinor.
1846 :
1847 : The purpose of this method is to ensure that calling code will run with the GDAL
1848 : version it is compiled for. It is primarly intented for external plugins.
1849 :
1850 : @param nVersionMajor Major version to be tested against
1851 : @param nVersionMinor Minor version to be tested against
1852 : @param pszCallingComponentName If not NULL, in case of version mismatch, the method
1853 : will issue a failure mentionning the name of
1854 : the calling component.
1855 :
1856 : @return TRUE if GDAL library version at runtime matches nVersionMajor.nVersionMinor, FALSE otherwise.
1857 : */
1858 : int CPL_STDCALL GDALCheckVersion( int nVersionMajor, int nVersionMinor,
1859 5417 : const char* pszCallingComponentName)
1860 : {
1861 5417 : if (nVersionMajor == GDAL_VERSION_MAJOR &&
1862 : nVersionMinor == GDAL_VERSION_MINOR)
1863 5417 : return TRUE;
1864 :
1865 0 : if (pszCallingComponentName)
1866 : {
1867 : CPLError( CE_Failure, CPLE_AppDefined,
1868 : "%s was compiled against GDAL %d.%d but current library version is %d.%d\n",
1869 : pszCallingComponentName, nVersionMajor, nVersionMinor,
1870 0 : GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR);
1871 : }
1872 0 : return FALSE;
1873 : }
1874 :
1875 : /************************************************************************/
1876 : /* GDALDecToDMS() */
1877 : /* */
1878 : /* Translate a decimal degrees value to a DMS string with */
1879 : /* hemisphere. */
1880 : /************************************************************************/
1881 :
1882 : const char * CPL_STDCALL GDALDecToDMS( double dfAngle, const char * pszAxis,
1883 260 : int nPrecision )
1884 :
1885 : {
1886 260 : return CPLDecToDMS( dfAngle, pszAxis, nPrecision );
1887 : }
1888 :
1889 : /************************************************************************/
1890 : /* GDALPackedDMSToDec() */
1891 : /************************************************************************/
1892 :
1893 : /**
1894 : * \brief Convert a packed DMS value (DDDMMMSSS.SS) into decimal degrees.
1895 : *
1896 : * See CPLPackedDMSToDec().
1897 : */
1898 :
1899 4 : double CPL_STDCALL GDALPackedDMSToDec( double dfPacked )
1900 :
1901 : {
1902 4 : return CPLPackedDMSToDec( dfPacked );
1903 : }
1904 :
1905 : /************************************************************************/
1906 : /* GDALDecToPackedDMS() */
1907 : /************************************************************************/
1908 :
1909 : /**
1910 : * \brief Convert decimal degrees into packed DMS value (DDDMMMSSS.SS).
1911 : *
1912 : * See CPLDecToPackedDMS().
1913 : */
1914 :
1915 4 : double CPL_STDCALL GDALDecToPackedDMS( double dfDec )
1916 :
1917 : {
1918 4 : return CPLDecToPackedDMS( dfDec );
1919 : }
1920 :
1921 : /************************************************************************/
1922 : /* GDALGCPsToGeoTransform() */
1923 : /************************************************************************/
1924 :
1925 : /**
1926 : * \brief Generate Geotransform from GCPs.
1927 : *
1928 : * Given a set of GCPs perform first order fit as a geotransform.
1929 : *
1930 : * Due to imprecision in the calculations the fit algorithm will often
1931 : * return non-zero rotational coefficients even if given perfectly non-rotated
1932 : * inputs. A special case has been implemented for corner corner coordinates
1933 : * given in TL, TR, BR, BL order. So when using this to get a geotransform
1934 : * from 4 corner coordinates, pass them in this order.
1935 : *
1936 : * @param nGCPCount the number of GCPs being passed in.
1937 : * @param pasGCPs the list of GCP structures.
1938 : * @param padfGeoTransform the six double array in which the affine
1939 : * geotransformation will be returned.
1940 : * @param bApproxOK If FALSE the function will fail if the geotransform is not
1941 : * essentially an exact fit (within 0.25 pixel) for all GCPs.
1942 : *
1943 : * @return TRUE on success or FALSE if there aren't enough points to prepare a
1944 : * geotransform, the pointers are ill-determined or if bApproxOK is FALSE
1945 : * and the fit is poor.
1946 : */
1947 :
1948 : int CPL_STDCALL
1949 : GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
1950 142 : double *padfGeoTransform, int bApproxOK )
1951 :
1952 : {
1953 : int i;
1954 :
1955 : /* -------------------------------------------------------------------- */
1956 : /* Recognise a few special cases. */
1957 : /* -------------------------------------------------------------------- */
1958 142 : if( nGCPCount < 2 )
1959 7 : return FALSE;
1960 :
1961 135 : if( nGCPCount == 2 )
1962 : {
1963 0 : if( pasGCPs[1].dfGCPPixel == pasGCPs[0].dfGCPPixel
1964 : || pasGCPs[1].dfGCPLine == pasGCPs[0].dfGCPLine )
1965 0 : return FALSE;
1966 :
1967 : padfGeoTransform[1] = (pasGCPs[1].dfGCPX - pasGCPs[0].dfGCPX)
1968 0 : / (pasGCPs[1].dfGCPPixel - pasGCPs[0].dfGCPPixel);
1969 0 : padfGeoTransform[2] = 0.0;
1970 :
1971 0 : padfGeoTransform[4] = 0.0;
1972 : padfGeoTransform[5] = (pasGCPs[1].dfGCPY - pasGCPs[0].dfGCPY)
1973 0 : / (pasGCPs[1].dfGCPLine - pasGCPs[0].dfGCPLine);
1974 :
1975 : padfGeoTransform[0] = pasGCPs[0].dfGCPX
1976 : - pasGCPs[0].dfGCPPixel * padfGeoTransform[1]
1977 0 : - pasGCPs[0].dfGCPLine * padfGeoTransform[2];
1978 :
1979 : padfGeoTransform[3] = pasGCPs[0].dfGCPY
1980 : - pasGCPs[0].dfGCPPixel * padfGeoTransform[4]
1981 0 : - pasGCPs[0].dfGCPLine * padfGeoTransform[5];
1982 :
1983 0 : return TRUE;
1984 : }
1985 :
1986 : /* -------------------------------------------------------------------- */
1987 : /* Special case of 4 corner coordinates of a non-rotated */
1988 : /* image. The points must be in TL-TR-BR-BL order for now. */
1989 : /* This case helps avoid some imprecision in the general */
1990 : /* calcuations. */
1991 : /* -------------------------------------------------------------------- */
1992 135 : if( nGCPCount == 4
1993 : && pasGCPs[0].dfGCPLine == pasGCPs[1].dfGCPLine
1994 : && pasGCPs[2].dfGCPLine == pasGCPs[3].dfGCPLine
1995 : && pasGCPs[0].dfGCPPixel == pasGCPs[3].dfGCPPixel
1996 : && pasGCPs[1].dfGCPPixel == pasGCPs[2].dfGCPPixel
1997 : && pasGCPs[0].dfGCPLine != pasGCPs[2].dfGCPLine
1998 : && pasGCPs[0].dfGCPPixel != pasGCPs[1].dfGCPPixel
1999 : && pasGCPs[0].dfGCPY == pasGCPs[1].dfGCPY
2000 : && pasGCPs[2].dfGCPY == pasGCPs[3].dfGCPY
2001 : && pasGCPs[0].dfGCPX == pasGCPs[3].dfGCPX
2002 : && pasGCPs[1].dfGCPX == pasGCPs[2].dfGCPX
2003 : && pasGCPs[0].dfGCPY != pasGCPs[2].dfGCPY
2004 : && pasGCPs[0].dfGCPX != pasGCPs[1].dfGCPX )
2005 : {
2006 : padfGeoTransform[1] = (pasGCPs[1].dfGCPX - pasGCPs[0].dfGCPX)
2007 84 : / (pasGCPs[1].dfGCPPixel - pasGCPs[0].dfGCPPixel);
2008 84 : padfGeoTransform[2] = 0.0;
2009 84 : padfGeoTransform[4] = 0.0;
2010 : padfGeoTransform[5] = (pasGCPs[2].dfGCPY - pasGCPs[1].dfGCPY)
2011 84 : / (pasGCPs[2].dfGCPLine - pasGCPs[1].dfGCPLine);
2012 :
2013 : padfGeoTransform[0] =
2014 84 : pasGCPs[0].dfGCPX - pasGCPs[0].dfGCPPixel * padfGeoTransform[1];
2015 : padfGeoTransform[3] =
2016 84 : pasGCPs[0].dfGCPY - pasGCPs[0].dfGCPLine * padfGeoTransform[5];
2017 84 : return TRUE;
2018 : }
2019 :
2020 : /* -------------------------------------------------------------------- */
2021 : /* In the general case, do a least squares error approximation by */
2022 : /* solving the equation Sum[(A - B*x + C*y - Lon)^2] = minimum */
2023 : /* -------------------------------------------------------------------- */
2024 :
2025 51 : double sum_x = 0.0, sum_y = 0.0, sum_xy = 0.0, sum_xx = 0.0, sum_yy = 0.0;
2026 51 : double sum_Lon = 0.0, sum_Lonx = 0.0, sum_Lony = 0.0;
2027 51 : double sum_Lat = 0.0, sum_Latx = 0.0, sum_Laty = 0.0;
2028 : double divisor;
2029 :
2030 257 : for (i = 0; i < nGCPCount; ++i) {
2031 206 : sum_x += pasGCPs[i].dfGCPPixel;
2032 206 : sum_y += pasGCPs[i].dfGCPLine;
2033 206 : sum_xy += pasGCPs[i].dfGCPPixel * pasGCPs[i].dfGCPLine;
2034 206 : sum_xx += pasGCPs[i].dfGCPPixel * pasGCPs[i].dfGCPPixel;
2035 206 : sum_yy += pasGCPs[i].dfGCPLine * pasGCPs[i].dfGCPLine;
2036 206 : sum_Lon += pasGCPs[i].dfGCPX;
2037 206 : sum_Lonx += pasGCPs[i].dfGCPX * pasGCPs[i].dfGCPPixel;
2038 206 : sum_Lony += pasGCPs[i].dfGCPX * pasGCPs[i].dfGCPLine;
2039 206 : sum_Lat += pasGCPs[i].dfGCPY;
2040 206 : sum_Latx += pasGCPs[i].dfGCPY * pasGCPs[i].dfGCPPixel;
2041 206 : sum_Laty += pasGCPs[i].dfGCPY * pasGCPs[i].dfGCPLine;
2042 : }
2043 :
2044 : divisor = nGCPCount * (sum_xx * sum_yy - sum_xy * sum_xy)
2045 : + 2 * sum_x * sum_y * sum_xy - sum_y * sum_y * sum_xx
2046 51 : - sum_x * sum_x * sum_yy;
2047 :
2048 : /* -------------------------------------------------------------------- */
2049 : /* If the divisor is zero, there is no valid solution. */
2050 : /* -------------------------------------------------------------------- */
2051 51 : if (divisor == 0.0)
2052 2 : return FALSE;
2053 :
2054 : /* -------------------------------------------------------------------- */
2055 : /* Compute top/left origin. */
2056 : /* -------------------------------------------------------------------- */
2057 :
2058 : padfGeoTransform[0] = (sum_Lon * (sum_xx * sum_yy - sum_xy * sum_xy)
2059 : + sum_Lonx * (sum_y * sum_xy - sum_x * sum_yy)
2060 : + sum_Lony * (sum_x * sum_xy - sum_y * sum_xx))
2061 49 : / divisor;
2062 :
2063 : padfGeoTransform[3] = (sum_Lat * (sum_xx * sum_yy - sum_xy * sum_xy)
2064 : + sum_Latx * (sum_y * sum_xy - sum_x * sum_yy)
2065 : + sum_Laty * (sum_x * sum_xy - sum_y * sum_xx))
2066 49 : / divisor;
2067 :
2068 : /* -------------------------------------------------------------------- */
2069 : /* Compute X related coefficients. */
2070 : /* -------------------------------------------------------------------- */
2071 : padfGeoTransform[1] = (sum_Lon * (sum_y * sum_xy - sum_x * sum_yy)
2072 : + sum_Lonx * (nGCPCount * sum_yy - sum_y * sum_y)
2073 : + sum_Lony * (sum_x * sum_y - sum_xy * nGCPCount))
2074 49 : / divisor;
2075 :
2076 : padfGeoTransform[2] = (sum_Lon * (sum_x * sum_xy - sum_y * sum_xx)
2077 : + sum_Lonx * (sum_x * sum_y - nGCPCount * sum_xy)
2078 : + sum_Lony * (nGCPCount * sum_xx - sum_x * sum_x))
2079 49 : / divisor;
2080 :
2081 : /* -------------------------------------------------------------------- */
2082 : /* Compute Y related coefficients. */
2083 : /* -------------------------------------------------------------------- */
2084 : padfGeoTransform[4] = (sum_Lat * (sum_y * sum_xy - sum_x * sum_yy)
2085 : + sum_Latx * (nGCPCount * sum_yy - sum_y * sum_y)
2086 : + sum_Laty * (sum_x * sum_y - sum_xy * nGCPCount))
2087 49 : / divisor;
2088 :
2089 : padfGeoTransform[5] = (sum_Lat * (sum_x * sum_xy - sum_y * sum_xx)
2090 : + sum_Latx * (sum_x * sum_y - nGCPCount * sum_xy)
2091 : + sum_Laty * (nGCPCount * sum_xx - sum_x * sum_x))
2092 49 : / divisor;
2093 :
2094 : /* -------------------------------------------------------------------- */
2095 : /* Now check if any of the input points fit this poorly. */
2096 : /* -------------------------------------------------------------------- */
2097 49 : if( !bApproxOK )
2098 : {
2099 : double dfPixelSize = ABS(padfGeoTransform[1])
2100 : + ABS(padfGeoTransform[2])
2101 : + ABS(padfGeoTransform[4])
2102 49 : + ABS(padfGeoTransform[5]);
2103 :
2104 247 : for( i = 0; i < nGCPCount; i++ )
2105 : {
2106 : double dfErrorX, dfErrorY;
2107 :
2108 : dfErrorX =
2109 : (pasGCPs[i].dfGCPPixel * padfGeoTransform[1]
2110 : + pasGCPs[i].dfGCPLine * padfGeoTransform[2]
2111 : + padfGeoTransform[0])
2112 198 : - pasGCPs[i].dfGCPX;
2113 : dfErrorY =
2114 : (pasGCPs[i].dfGCPPixel * padfGeoTransform[4]
2115 : + pasGCPs[i].dfGCPLine * padfGeoTransform[5]
2116 : + padfGeoTransform[3])
2117 198 : - pasGCPs[i].dfGCPY;
2118 :
2119 198 : if( ABS(dfErrorX) > 0.25 * dfPixelSize
2120 : || ABS(dfErrorY) > 0.25 * dfPixelSize )
2121 0 : return FALSE;
2122 : }
2123 : }
2124 :
2125 49 : return TRUE;
2126 : }
2127 :
2128 : /************************************************************************/
2129 : /* GDALGeneralCmdLineProcessor() */
2130 : /************************************************************************/
2131 :
2132 : /**
2133 : * \brief General utility option processing.
2134 : *
2135 : * This function is intended to provide a variety of generic commandline
2136 : * options for all GDAL commandline utilities. It takes care of the following
2137 : * commandline options:
2138 : *
2139 : * --version: report version of GDAL in use.
2140 : * --license: report GDAL license info.
2141 : * --formats: report all format drivers configured.
2142 : * --format [format]: report details of one format driver.
2143 : * --optfile filename: expand an option file into the argument list.
2144 : * --config key value: set system configuration option.
2145 : * --debug [on/off/value]: set debug level.
2146 : * --mempreload dir: preload directory contents into /vsimem
2147 : * --help-general: report detailed help on general options.
2148 : *
2149 : * The argument array is replaced "in place" and should be freed with
2150 : * CSLDestroy() when no longer needed. The typical usage looks something
2151 : * like the following. Note that the formats should be registered so that
2152 : * the --formats and --format options will work properly.
2153 : *
2154 : * int main( int argc, char ** argv )
2155 : * {
2156 : * GDALAllRegister();
2157 : *
2158 : * argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
2159 : * if( argc < 1 )
2160 : * exit( -argc );
2161 : *
2162 : * @param nArgc number of values in the argument list.
2163 : * @param Pointer to the argument list array (will be updated in place).
2164 : *
2165 : * @return updated nArgc argument count. Return of 0 requests terminate
2166 : * without error, return of -1 requests exit with error code.
2167 : */
2168 :
2169 : int CPL_STDCALL
2170 426 : GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
2171 :
2172 : {
2173 426 : char **papszReturn = NULL;
2174 : int iArg;
2175 426 : char **papszArgv = *ppapszArgv;
2176 :
2177 : (void) nOptions;
2178 :
2179 : /* -------------------------------------------------------------------- */
2180 : /* Preserve the program name. */
2181 : /* -------------------------------------------------------------------- */
2182 426 : papszReturn = CSLAddString( papszReturn, papszArgv[0] );
2183 :
2184 : /* ==================================================================== */
2185 : /* Loop over all arguments. */
2186 : /* ==================================================================== */
2187 2336 : for( iArg = 1; iArg < nArgc; iArg++ )
2188 : {
2189 : /* -------------------------------------------------------------------- */
2190 : /* --version */
2191 : /* -------------------------------------------------------------------- */
2192 1910 : if( EQUAL(papszArgv[iArg],"--version") )
2193 : {
2194 0 : printf( "%s\n", GDALVersionInfo( "--version" ) );
2195 0 : CSLDestroy( papszReturn );
2196 0 : return 0;
2197 : }
2198 :
2199 : /* -------------------------------------------------------------------- */
2200 : /* --license */
2201 : /* -------------------------------------------------------------------- */
2202 1910 : else if( EQUAL(papszArgv[iArg],"--license") )
2203 : {
2204 0 : printf( "%s\n", GDALVersionInfo( "LICENSE" ) );
2205 0 : CSLDestroy( papszReturn );
2206 0 : return 0;
2207 : }
2208 :
2209 : /* -------------------------------------------------------------------- */
2210 : /* --config */
2211 : /* -------------------------------------------------------------------- */
2212 1910 : else if( EQUAL(papszArgv[iArg],"--config") )
2213 : {
2214 2 : if( iArg + 2 >= nArgc )
2215 : {
2216 : CPLError( CE_Failure, CPLE_AppDefined,
2217 0 : "--config option given without a key and value argument." );
2218 0 : CSLDestroy( papszReturn );
2219 0 : return -1;
2220 : }
2221 :
2222 2 : CPLSetConfigOption( papszArgv[iArg+1], papszArgv[iArg+2] );
2223 :
2224 2 : iArg += 2;
2225 : }
2226 :
2227 : /* -------------------------------------------------------------------- */
2228 : /* --mempreload */
2229 : /* -------------------------------------------------------------------- */
2230 1908 : else if( EQUAL(papszArgv[iArg],"--mempreload") )
2231 : {
2232 : int i;
2233 :
2234 0 : if( iArg + 1 >= nArgc )
2235 : {
2236 : CPLError( CE_Failure, CPLE_AppDefined,
2237 0 : "--mempreload option given without directory path.");
2238 0 : CSLDestroy( papszReturn );
2239 0 : return -1;
2240 : }
2241 :
2242 0 : char **papszFiles = CPLReadDir( papszArgv[iArg+1] );
2243 0 : if( CSLCount(papszFiles) == 0 )
2244 : {
2245 : CPLError( CE_Failure, CPLE_AppDefined,
2246 0 : "--mempreload given invalid or empty directory.");
2247 0 : CSLDestroy( papszReturn );
2248 0 : return -1;
2249 : }
2250 :
2251 0 : for( i = 0; papszFiles[i] != NULL; i++ )
2252 : {
2253 0 : CPLString osOldPath, osNewPath;
2254 :
2255 0 : if( EQUAL(papszFiles[i],".") || EQUAL(papszFiles[i],"..") )
2256 0 : continue;
2257 :
2258 : osOldPath = CPLFormFilename( papszArgv[iArg+1],
2259 0 : papszFiles[i], NULL );
2260 0 : osNewPath.Printf( "/vsimem/%s", papszFiles[i] );
2261 :
2262 : CPLDebug( "VSI", "Preloading %s to %s.",
2263 0 : osOldPath.c_str(), osNewPath.c_str() );
2264 :
2265 0 : if( CPLCopyFile( osNewPath, osOldPath ) != 0 )
2266 0 : return -1;
2267 : }
2268 :
2269 0 : CSLDestroy( papszFiles );
2270 0 : iArg += 1;
2271 : }
2272 :
2273 : /* -------------------------------------------------------------------- */
2274 : /* --debug */
2275 : /* -------------------------------------------------------------------- */
2276 1908 : else if( EQUAL(papszArgv[iArg],"--debug") )
2277 : {
2278 0 : if( iArg + 1 >= nArgc )
2279 : {
2280 : CPLError( CE_Failure, CPLE_AppDefined,
2281 0 : "--debug option given without debug level." );
2282 0 : CSLDestroy( papszReturn );
2283 0 : return -1;
2284 : }
2285 :
2286 0 : CPLSetConfigOption( "CPL_DEBUG", papszArgv[iArg+1] );
2287 0 : iArg += 1;
2288 : }
2289 :
2290 : /* -------------------------------------------------------------------- */
2291 : /* --optfile */
2292 : /* */
2293 : /* Annoyingly the options inserted by --optfile will *not* be */
2294 : /* processed properly if they are general options. */
2295 : /* -------------------------------------------------------------------- */
2296 1908 : else if( EQUAL(papszArgv[iArg],"--optfile") )
2297 : {
2298 : const char *pszLine;
2299 : FILE *fpOptFile;
2300 :
2301 0 : if( iArg + 1 >= nArgc )
2302 : {
2303 : CPLError( CE_Failure, CPLE_AppDefined,
2304 0 : "--optfile option given without filename." );
2305 0 : CSLDestroy( papszReturn );
2306 0 : return -1;
2307 : }
2308 :
2309 0 : fpOptFile = VSIFOpen( papszArgv[iArg+1], "rb" );
2310 :
2311 0 : if( fpOptFile == NULL )
2312 : {
2313 : CPLError( CE_Failure, CPLE_AppDefined,
2314 : "Unable to open optfile '%s'.\n%s",
2315 0 : papszArgv[iArg+1], VSIStrerror( errno ) );
2316 0 : CSLDestroy( papszReturn );
2317 0 : return -1;
2318 : }
2319 :
2320 0 : while( (pszLine = CPLReadLine( fpOptFile )) != NULL )
2321 : {
2322 : char **papszTokens;
2323 : int i;
2324 :
2325 0 : if( pszLine[0] == '#' || strlen(pszLine) == 0 )
2326 0 : continue;
2327 :
2328 0 : papszTokens = CSLTokenizeString( pszLine );
2329 0 : for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++)
2330 0 : papszReturn = CSLAddString( papszReturn, papszTokens[i] );
2331 0 : CSLDestroy( papszTokens );
2332 : }
2333 :
2334 0 : VSIFClose( fpOptFile );
2335 :
2336 0 : iArg += 1;
2337 : }
2338 :
2339 : /* -------------------------------------------------------------------- */
2340 : /* --formats */
2341 : /* -------------------------------------------------------------------- */
2342 1908 : else if( EQUAL(papszArgv[iArg], "--formats") )
2343 : {
2344 : int iDr;
2345 :
2346 0 : printf( "Supported Formats:\n" );
2347 0 : for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
2348 : {
2349 0 : GDALDriverH hDriver = GDALGetDriver(iDr);
2350 : const char *pszRWFlag, *pszVirtualIO;
2351 :
2352 0 : if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) )
2353 0 : pszRWFlag = "rw+";
2354 0 : else if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY,
2355 : NULL ) )
2356 0 : pszRWFlag = "rw";
2357 : else
2358 0 : pszRWFlag = "ro";
2359 :
2360 0 : if( GDALGetMetadataItem( hDriver, GDAL_DCAP_VIRTUALIO, NULL) )
2361 0 : pszVirtualIO = "v";
2362 : else
2363 0 : pszVirtualIO = "";
2364 :
2365 : printf( " %s (%s%s): %s\n",
2366 : GDALGetDriverShortName( hDriver ),
2367 : pszRWFlag, pszVirtualIO,
2368 0 : GDALGetDriverLongName( hDriver ) );
2369 : }
2370 :
2371 0 : CSLDestroy( papszReturn );
2372 0 : return 0;
2373 : }
2374 :
2375 : /* -------------------------------------------------------------------- */
2376 : /* --format */
2377 : /* -------------------------------------------------------------------- */
2378 1908 : else if( EQUAL(papszArgv[iArg], "--format") )
2379 : {
2380 : GDALDriverH hDriver;
2381 : char **papszMD;
2382 :
2383 0 : CSLDestroy( papszReturn );
2384 :
2385 0 : if( iArg + 1 >= nArgc )
2386 : {
2387 : CPLError( CE_Failure, CPLE_AppDefined,
2388 0 : "--format option given without a format code." );
2389 0 : return -1;
2390 : }
2391 :
2392 0 : hDriver = GDALGetDriverByName( papszArgv[iArg+1] );
2393 0 : if( hDriver == NULL )
2394 : {
2395 : CPLError( CE_Failure, CPLE_AppDefined,
2396 : "--format option given with format '%s', but that format not\n"
2397 : "recognised. Use the --formats option to get a list of available formats,\n"
2398 : "and use the short code (ie. GTiff or HFA) as the format identifier.\n",
2399 0 : papszArgv[iArg+1] );
2400 0 : return -1;
2401 : }
2402 :
2403 0 : printf( "Format Details:\n" );
2404 0 : printf( " Short Name: %s\n", GDALGetDriverShortName( hDriver ) );
2405 0 : printf( " Long Name: %s\n", GDALGetDriverLongName( hDriver ) );
2406 :
2407 0 : papszMD = GDALGetMetadata( hDriver, NULL );
2408 :
2409 0 : if( CSLFetchNameValue( papszMD, GDAL_DMD_EXTENSION ) )
2410 : printf( " Extension: %s\n",
2411 0 : CSLFetchNameValue( papszMD, GDAL_DMD_EXTENSION ) );
2412 0 : if( CSLFetchNameValue( papszMD, GDAL_DMD_MIMETYPE ) )
2413 : printf( " Mime Type: %s\n",
2414 0 : CSLFetchNameValue( papszMD, GDAL_DMD_MIMETYPE ) );
2415 0 : if( CSLFetchNameValue( papszMD, GDAL_DMD_HELPTOPIC ) )
2416 : printf( " Help Topic: %s\n",
2417 0 : CSLFetchNameValue( papszMD, GDAL_DMD_HELPTOPIC ) );
2418 :
2419 0 : if( CSLFetchBoolean( papszMD, GDAL_DCAP_CREATE, FALSE ) )
2420 0 : printf( " Supports: Create() - Create writeable dataset.\n" );
2421 0 : if( CSLFetchBoolean( papszMD, GDAL_DCAP_CREATECOPY, FALSE ) )
2422 0 : printf( " Supports: CreateCopy() - Create dataset by copying another.\n" );
2423 0 : if( CSLFetchBoolean( papszMD, GDAL_DCAP_VIRTUALIO, FALSE ) )
2424 0 : printf( " Supports: Virtual IO - eg. /vsimem/\n" );
2425 0 : if( CSLFetchNameValue( papszMD, GDAL_DMD_CREATIONDATATYPES ) )
2426 : printf( " Creation Datatypes: %s\n",
2427 0 : CSLFetchNameValue( papszMD, GDAL_DMD_CREATIONDATATYPES ) );
2428 0 : if( CSLFetchNameValue( papszMD, GDAL_DMD_CREATIONOPTIONLIST ) )
2429 : {
2430 : CPLXMLNode *psCOL =
2431 : CPLParseXMLString(
2432 : CSLFetchNameValue( papszMD,
2433 0 : GDAL_DMD_CREATIONOPTIONLIST ) );
2434 : char *pszFormattedXML =
2435 0 : CPLSerializeXMLTree( psCOL );
2436 :
2437 0 : CPLDestroyXMLNode( psCOL );
2438 :
2439 0 : printf( "\n%s\n", pszFormattedXML );
2440 0 : CPLFree( pszFormattedXML );
2441 : }
2442 0 : return 0;
2443 : }
2444 :
2445 : /* -------------------------------------------------------------------- */
2446 : /* --help-general */
2447 : /* -------------------------------------------------------------------- */
2448 1908 : else if( EQUAL(papszArgv[iArg],"--help-general") )
2449 : {
2450 0 : printf( "Generic GDAL utility command options:\n" );
2451 0 : printf( " --version: report version of GDAL in use.\n" );
2452 0 : printf( " --license: report GDAL license info.\n" );
2453 0 : printf( " --formats: report all configured format drivers.\n" );
2454 0 : printf( " --format [format]: details of one format.\n" );
2455 0 : printf( " --optfile filename: expand an option file into the argument list.\n" );
2456 0 : printf( " --config key value: set system configuration option.\n" );
2457 0 : printf( " --debug [on/off/value]: set debug level.\n" );
2458 0 : printf( " --help-general: report detailed help on general options.\n" );
2459 0 : CSLDestroy( papszReturn );
2460 0 : return 0;
2461 : }
2462 :
2463 : /* -------------------------------------------------------------------- */
2464 : /* --locale */
2465 : /* -------------------------------------------------------------------- */
2466 1908 : else if( EQUAL(papszArgv[iArg],"--locale") && iArg < nArgc-1 )
2467 : {
2468 0 : setlocale( LC_ALL, papszArgv[++iArg] );
2469 : }
2470 :
2471 : /* -------------------------------------------------------------------- */
2472 : /* carry through unrecognised options. */
2473 : /* -------------------------------------------------------------------- */
2474 : else
2475 : {
2476 1908 : papszReturn = CSLAddString( papszReturn, papszArgv[iArg] );
2477 : }
2478 : }
2479 :
2480 426 : *ppapszArgv = papszReturn;
2481 :
2482 426 : return CSLCount( *ppapszArgv );
2483 : }
2484 :
2485 :
2486 : /************************************************************************/
2487 : /* _FetchDblFromMD() */
2488 : /************************************************************************/
2489 :
2490 : static int _FetchDblFromMD( char **papszMD, const char *pszKey,
2491 72 : double *padfTarget, int nCount, double dfDefault )
2492 :
2493 : {
2494 : char szFullKey[200];
2495 :
2496 72 : sprintf( szFullKey, "%s", pszKey );
2497 :
2498 72 : const char *pszValue = CSLFetchNameValue( papszMD, szFullKey );
2499 : int i;
2500 :
2501 448 : for( i = 0; i < nCount; i++ )
2502 376 : padfTarget[i] = dfDefault;
2503 :
2504 72 : if( pszValue == NULL )
2505 16 : return FALSE;
2506 :
2507 56 : if( nCount == 1 )
2508 : {
2509 40 : *padfTarget = CPLAtofM( pszValue );
2510 40 : return TRUE;
2511 : }
2512 :
2513 : char **papszTokens = CSLTokenizeStringComplex( pszValue, " ,",
2514 16 : FALSE, FALSE );
2515 :
2516 16 : if( CSLCount( papszTokens ) != nCount )
2517 : {
2518 0 : CSLDestroy( papszTokens );
2519 0 : return FALSE;
2520 : }
2521 :
2522 336 : for( i = 0; i < nCount; i++ )
2523 320 : padfTarget[i] = CPLAtofM(papszTokens[i]);
2524 :
2525 16 : CSLDestroy( papszTokens );
2526 :
2527 16 : return TRUE;
2528 : }
2529 :
2530 : /************************************************************************/
2531 : /* GDALExtractRPCInfo() */
2532 : /* */
2533 : /* Extract RPC info from metadata, and apply to an RPCInfo */
2534 : /* structure. The inverse of this function is RPCInfoToMD() in */
2535 : /* alg/gdal_rpc.cpp (should it be needed). */
2536 : /************************************************************************/
2537 :
2538 4 : int CPL_STDCALL GDALExtractRPCInfo( char **papszMD, GDALRPCInfo *psRPC )
2539 :
2540 : {
2541 4 : if( CSLFetchNameValue( papszMD, "LINE_NUM_COEFF" ) == NULL )
2542 0 : return FALSE;
2543 :
2544 4 : if( CSLFetchNameValue( papszMD, "LINE_NUM_COEFF" ) == NULL
2545 : || CSLFetchNameValue( papszMD, "LINE_DEN_COEFF" ) == NULL
2546 : || CSLFetchNameValue( papszMD, "SAMP_NUM_COEFF" ) == NULL
2547 : || CSLFetchNameValue( papszMD, "SAMP_DEN_COEFF" ) == NULL )
2548 : {
2549 : CPLError( CE_Failure, CPLE_AppDefined,
2550 0 : "Some required RPC metadata missing in GDALExtractRPCInfo()");
2551 0 : return FALSE;
2552 : }
2553 :
2554 4 : _FetchDblFromMD( papszMD, "LINE_OFF", &(psRPC->dfLINE_OFF), 1, 0.0 );
2555 4 : _FetchDblFromMD( papszMD, "LINE_SCALE", &(psRPC->dfLINE_SCALE), 1, 1.0 );
2556 4 : _FetchDblFromMD( papszMD, "SAMP_OFF", &(psRPC->dfSAMP_OFF), 1, 0.0 );
2557 4 : _FetchDblFromMD( papszMD, "SAMP_SCALE", &(psRPC->dfSAMP_SCALE), 1, 1.0 );
2558 4 : _FetchDblFromMD( papszMD, "HEIGHT_OFF", &(psRPC->dfHEIGHT_OFF), 1, 0.0 );
2559 4 : _FetchDblFromMD( papszMD, "HEIGHT_SCALE", &(psRPC->dfHEIGHT_SCALE),1, 1.0);
2560 4 : _FetchDblFromMD( papszMD, "LAT_OFF", &(psRPC->dfLAT_OFF), 1, 0.0 );
2561 4 : _FetchDblFromMD( papszMD, "LAT_SCALE", &(psRPC->dfLAT_SCALE), 1, 1.0 );
2562 4 : _FetchDblFromMD( papszMD, "LONG_OFF", &(psRPC->dfLONG_OFF), 1, 0.0 );
2563 4 : _FetchDblFromMD( papszMD, "LONG_SCALE", &(psRPC->dfLONG_SCALE), 1, 1.0 );
2564 :
2565 : _FetchDblFromMD( papszMD, "LINE_NUM_COEFF", psRPC->adfLINE_NUM_COEFF,
2566 4 : 20, 0.0 );
2567 : _FetchDblFromMD( papszMD, "LINE_DEN_COEFF", psRPC->adfLINE_DEN_COEFF,
2568 4 : 20, 0.0 );
2569 : _FetchDblFromMD( papszMD, "SAMP_NUM_COEFF", psRPC->adfSAMP_NUM_COEFF,
2570 4 : 20, 0.0 );
2571 : _FetchDblFromMD( papszMD, "SAMP_DEN_COEFF", psRPC->adfSAMP_DEN_COEFF,
2572 4 : 20, 0.0 );
2573 :
2574 4 : _FetchDblFromMD( papszMD, "MIN_LONG", &(psRPC->dfMIN_LONG), 1, -180.0 );
2575 4 : _FetchDblFromMD( papszMD, "MIN_LAT", &(psRPC->dfMIN_LAT), 1, -90.0 );
2576 4 : _FetchDblFromMD( papszMD, "MAX_LONG", &(psRPC->dfMAX_LONG), 1, 180.0 );
2577 4 : _FetchDblFromMD( papszMD, "MAX_LAT", &(psRPC->dfMAX_LAT), 1, 90.0 );
2578 :
2579 4 : return TRUE;
2580 : }
2581 :
2582 : /************************************************************************/
2583 : /* GDALFindAssociatedAuxFile() */
2584 : /************************************************************************/
2585 :
2586 : GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
2587 : GDALAccess eAccess,
2588 7239 : GDALDataset *poDependentDS )
2589 :
2590 : {
2591 7239 : const char *pszAuxSuffixLC = "aux";
2592 : #ifndef WIN32
2593 7239 : const char *pszAuxSuffixUC = "AUX";
2594 : #endif
2595 :
2596 7239 : if( EQUAL(CPLGetExtension(pszBasename), pszAuxSuffixLC) )
2597 18 : return NULL;
2598 :
2599 : /* -------------------------------------------------------------------- */
2600 : /* Don't even try to look for an .aux file if we don't have a */
2601 : /* path of any kind. */
2602 : /* -------------------------------------------------------------------- */
2603 7221 : if( strlen(pszBasename) == 0 )
2604 0 : return NULL;
2605 :
2606 : /* -------------------------------------------------------------------- */
2607 : /* We didn't find that, so try and find a corresponding aux */
2608 : /* file. Check that we are the dependent file of the aux */
2609 : /* file, or if we aren't verify that the dependent file does */
2610 : /* not exist, likely mean it is us but some sort of renaming */
2611 : /* has occured. */
2612 : /* -------------------------------------------------------------------- */
2613 7221 : CPLString osJustFile = CPLGetFilename(pszBasename); // without dir
2614 7221 : CPLString osAuxFilename = CPLResetExtension(pszBasename, pszAuxSuffixLC);
2615 7221 : GDALDataset *poODS = NULL;
2616 : GByte abyHeader[32];
2617 : FILE *fp;
2618 :
2619 7221 : fp = VSIFOpenL( osAuxFilename, "rb" );
2620 :
2621 :
2622 7221 : if ( fp == NULL )
2623 : {
2624 : // Can't found file with lower case suffix. Try the upper case one.
2625 : // no point in doing this on Win32 with case insensitive filenames.
2626 : #ifndef WIN32
2627 7187 : osAuxFilename = CPLResetExtension(pszBasename, pszAuxSuffixUC);
2628 7187 : fp = VSIFOpenL( osAuxFilename, "rb" );
2629 : #endif
2630 : }
2631 :
2632 7221 : if( fp != NULL )
2633 : {
2634 34 : VSIFReadL( abyHeader, 1, 32, fp );
2635 34 : if( EQUALN((char *) abyHeader,"EHFA_HEADER_TAG",15) )
2636 : {
2637 : /* Avoid causing failure in opening of main file from SWIG bindings */
2638 : /* when auxiliary file cannot be opened (#3269) */
2639 10 : CPLTurnFailureIntoWarning(TRUE);
2640 10 : poODS = (GDALDataset *) GDALOpenShared( osAuxFilename, eAccess );
2641 10 : CPLTurnFailureIntoWarning(FALSE);
2642 : }
2643 34 : VSIFCloseL( fp );
2644 : }
2645 :
2646 : /* -------------------------------------------------------------------- */
2647 : /* Try replacing extension with .aux */
2648 : /* -------------------------------------------------------------------- */
2649 7221 : if( poODS != NULL )
2650 : {
2651 : const char *pszDep
2652 10 : = poODS->GetMetadataItem( "HFA_DEPENDENT_FILE", "HFA" );
2653 10 : if( pszDep == NULL )
2654 : {
2655 : CPLDebug( "AUX",
2656 : "Found %s but it has no dependent file, ignoring.",
2657 0 : osAuxFilename.c_str() );
2658 0 : GDALClose( poODS );
2659 0 : poODS = NULL;
2660 : }
2661 10 : else if( !EQUAL(pszDep,osJustFile) )
2662 : {
2663 : VSIStatBufL sStatBuf;
2664 :
2665 0 : if( VSIStatL( pszDep, &sStatBuf ) == 0 )
2666 : {
2667 : CPLDebug( "AUX", "%s is for file %s, not %s, ignoring.",
2668 : osAuxFilename.c_str(),
2669 0 : pszDep, osJustFile.c_str() );
2670 0 : GDALClose( poODS );
2671 0 : poODS = NULL;
2672 : }
2673 : else
2674 : {
2675 : CPLDebug( "AUX", "%s is for file %s, not %s, but since\n"
2676 : "%s does not exist, we will use .aux file as our own.",
2677 : osAuxFilename.c_str(),
2678 : pszDep, osJustFile.c_str(),
2679 0 : pszDep );
2680 : }
2681 : }
2682 :
2683 : /* -------------------------------------------------------------------- */
2684 : /* Confirm that the aux file matches the configuration of the */
2685 : /* dependent dataset. */
2686 : /* -------------------------------------------------------------------- */
2687 10 : if( poODS != NULL && poDependentDS != NULL
2688 : && (poODS->GetRasterCount() != poDependentDS->GetRasterCount()
2689 : || poODS->GetRasterXSize() != poDependentDS->GetRasterXSize()
2690 : || poODS->GetRasterYSize() != poDependentDS->GetRasterYSize()) )
2691 : {
2692 : CPLDebug( "AUX",
2693 : "Ignoring aux file %s as its raster configuration\n"
2694 : "(%dP x %dL x %dB) does not match master file (%dP x %dL x %dB)",
2695 : osAuxFilename.c_str(),
2696 : poODS->GetRasterXSize(),
2697 : poODS->GetRasterYSize(),
2698 : poODS->GetRasterCount(),
2699 : poDependentDS->GetRasterXSize(),
2700 : poDependentDS->GetRasterYSize(),
2701 5 : poDependentDS->GetRasterCount() );
2702 :
2703 5 : GDALClose( poODS );
2704 5 : poODS = NULL;
2705 : }
2706 : }
2707 :
2708 : /* -------------------------------------------------------------------- */
2709 : /* Try appending .aux to the end of the filename. */
2710 : /* -------------------------------------------------------------------- */
2711 7221 : if( poODS == NULL )
2712 : {
2713 7216 : osAuxFilename = pszBasename;
2714 7216 : osAuxFilename += ".";
2715 7216 : osAuxFilename += pszAuxSuffixLC;
2716 7216 : fp = VSIFOpenL( osAuxFilename, "rb" );
2717 : #ifndef WIN32
2718 7216 : if ( fp == NULL )
2719 : {
2720 : // Can't found file with lower case suffix. Try the upper case one.
2721 7197 : osAuxFilename = pszBasename;
2722 7197 : osAuxFilename += ".";
2723 7197 : osAuxFilename += pszAuxSuffixUC;
2724 7197 : fp = VSIFOpenL( osAuxFilename, "rb" );
2725 : }
2726 : #endif
2727 :
2728 7216 : if( fp != NULL )
2729 : {
2730 19 : VSIFReadL( abyHeader, 1, 32, fp );
2731 19 : if( EQUALN((char *) abyHeader,"EHFA_HEADER_TAG",15) )
2732 : {
2733 : /* Avoid causing failure in opening of main file from SWIG bindings */
2734 : /* when auxiliary file cannot be opened (#3269) */
2735 0 : CPLTurnFailureIntoWarning(TRUE);
2736 0 : poODS = (GDALDataset *) GDALOpenShared( osAuxFilename, eAccess );
2737 0 : CPLTurnFailureIntoWarning(FALSE);
2738 : }
2739 19 : VSIFCloseL( fp );
2740 : }
2741 :
2742 7216 : if( poODS != NULL )
2743 : {
2744 : const char *pszDep
2745 0 : = poODS->GetMetadataItem( "HFA_DEPENDENT_FILE", "HFA" );
2746 0 : if( pszDep == NULL )
2747 : {
2748 : CPLDebug( "AUX",
2749 : "Found %s but it has no dependent file, ignoring.",
2750 0 : osAuxFilename.c_str() );
2751 0 : GDALClose( poODS );
2752 0 : poODS = NULL;
2753 : }
2754 0 : else if( !EQUAL(pszDep,osJustFile) )
2755 : {
2756 : VSIStatBufL sStatBuf;
2757 :
2758 0 : if( VSIStatL( pszDep, &sStatBuf ) == 0 )
2759 : {
2760 : CPLDebug( "AUX", "%s is for file %s, not %s, ignoring.",
2761 : osAuxFilename.c_str(),
2762 0 : pszDep, osJustFile.c_str() );
2763 0 : GDALClose( poODS );
2764 0 : poODS = NULL;
2765 : }
2766 : else
2767 : {
2768 : CPLDebug( "AUX", "%s is for file %s, not %s, but since\n"
2769 : "%s does not exist, we will use .aux file as our own.",
2770 : osAuxFilename.c_str(),
2771 : pszDep, osJustFile.c_str(),
2772 0 : pszDep );
2773 : }
2774 : }
2775 : }
2776 : }
2777 :
2778 : /* -------------------------------------------------------------------- */
2779 : /* Confirm that the aux file matches the configuration of the */
2780 : /* dependent dataset. */
2781 : /* -------------------------------------------------------------------- */
2782 7221 : if( poODS != NULL && poDependentDS != NULL
2783 : && (poODS->GetRasterCount() != poDependentDS->GetRasterCount()
2784 : || poODS->GetRasterXSize() != poDependentDS->GetRasterXSize()
2785 : || poODS->GetRasterYSize() != poDependentDS->GetRasterYSize()) )
2786 : {
2787 : CPLDebug( "AUX",
2788 : "Ignoring aux file %s as its raster configuration\n"
2789 : "(%dP x %dL x %dB) does not match master file (%dP x %dL x %dB)",
2790 : osAuxFilename.c_str(),
2791 : poODS->GetRasterXSize(),
2792 : poODS->GetRasterYSize(),
2793 : poODS->GetRasterCount(),
2794 : poDependentDS->GetRasterXSize(),
2795 : poDependentDS->GetRasterYSize(),
2796 0 : poDependentDS->GetRasterCount() );
2797 :
2798 0 : GDALClose( poODS );
2799 0 : poODS = NULL;
2800 : }
2801 :
2802 7221 : return poODS;
2803 : }
2804 :
2805 : /************************************************************************/
2806 : /* -------------------------------------------------------------------- */
2807 : /* The following stubs are present to ensure that older GDAL */
2808 : /* bridges don't fail with newer libraries. */
2809 : /* -------------------------------------------------------------------- */
2810 : /************************************************************************/
2811 :
2812 : CPL_C_START
2813 :
2814 0 : void * CPL_STDCALL GDALCreateProjDef( const char * )
2815 : {
2816 0 : CPLDebug( "GDAL", "GDALCreateProjDef no longer supported." );
2817 0 : return NULL;
2818 : }
2819 :
2820 0 : CPLErr CPL_STDCALL GDALReprojectToLongLat( void *, double *, double * )
2821 : {
2822 0 : CPLDebug( "GDAL", "GDALReprojectToLatLong no longer supported." );
2823 0 : return CE_Failure;
2824 : }
2825 :
2826 0 : CPLErr CPL_STDCALL GDALReprojectFromLongLat( void *, double *, double * )
2827 : {
2828 0 : CPLDebug( "GDAL", "GDALReprojectFromLatLong no longer supported." );
2829 0 : return CE_Failure;
2830 : }
2831 :
2832 0 : void CPL_STDCALL GDALDestroyProjDef( void * )
2833 :
2834 : {
2835 0 : CPLDebug( "GDAL", "GDALDestroyProjDef no longer supported." );
2836 0 : }
2837 :
2838 : CPL_C_END
2839 :
2840 : /************************************************************************/
2841 : /* Infrastructure to check that dataset characteristics are valid */
2842 : /************************************************************************/
2843 :
2844 : CPL_C_START
2845 :
2846 : /**
2847 : * \brief Return TRUE if the dataset dimensions are valid.
2848 : *
2849 : * @param nXSize raster width
2850 : * @param nYSize raster height
2851 : *
2852 : * @since GDAL 1.7.0
2853 : */
2854 978 : int GDALCheckDatasetDimensions( int nXSize, int nYSize )
2855 : {
2856 978 : if (nXSize <= 0 || nYSize <= 0)
2857 : {
2858 : CPLError(CE_Failure, CPLE_AppDefined,
2859 0 : "Invalid dataset dimensions : %d x %d", nXSize, nYSize);
2860 0 : return FALSE;
2861 : }
2862 978 : return TRUE;
2863 : }
2864 :
2865 : /**
2866 : * \brief Return TRUE if the band count is valid.
2867 : *
2868 : * If the configuration option GDAL_MAX_BAND_COUNT is defined,
2869 : * the band count will be compared to the maximum number of band allowed.
2870 : *
2871 : * @param nBands the band count
2872 : * @param bIsZeroAllowed TRUE if band count == 0 is allowed
2873 : *
2874 : * @since GDAL 1.7.0
2875 : */
2876 :
2877 381 : int GDALCheckBandCount( int nBands, int bIsZeroAllowed )
2878 : {
2879 381 : int nMaxBands = -1;
2880 381 : const char* pszMaxBandCount = CPLGetConfigOption("GDAL_MAX_BAND_COUNT", NULL);
2881 381 : if (pszMaxBandCount != NULL)
2882 : {
2883 0 : nMaxBands = atoi(pszMaxBandCount);
2884 : }
2885 381 : if (nBands < 0 || (!bIsZeroAllowed && nBands == 0) ||
2886 : (nMaxBands >= 0 && nBands > nMaxBands) )
2887 : {
2888 : CPLError(CE_Failure, CPLE_AppDefined,
2889 4 : "Invalid band count : %d", nBands);
2890 4 : return FALSE;
2891 : }
2892 377 : return TRUE;
2893 : }
2894 :
2895 : CPL_C_END
2896 :
|