LTP GCOV extension - code coverage report
Current view: directory - gcore - gdal_misc.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 905
Code covered: 52.7 % Executed lines: 477

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

Generated by: LTP GCOV extension version 1.5