LCOV - code coverage report
Current view: directory - gcore - gdal_misc.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1006 747 74.3 %
Date: 2013-03-30 Functions: 41 31 75.6 %

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

Generated by: LCOV version 1.7