LCOV - code coverage report
Current view: directory - gcore - gdal_misc.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 927 463 49.9 %
Date: 2010-01-09 Functions: 41 33 80.5 %

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

Generated by: LCOV version 1.7