LCOV - code coverage report
Current view: directory - gcore - gdal_misc.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1031 643 62.4 %
Date: 2012-04-28 Functions: 46 37 80.4 %

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

Generated by: LCOV version 1.7