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