Main Page Class Hierarchy Compound List File List Compound Members File Members Related Pages

# gdal_misc.cpp

    00001 /******************************************************************************
    00002  * $Id: gdal_misc_cpp-source.html,v 1.8 2001/07/05 13:24:08 warmerda Exp $
    00003  *
    00004  * Project:  GDAL Core
    00005  * Purpose:  Free standing functions for GDAL.
    00006  * Author:   Frank Warmerdam, warmerda@home.com
    00007  *
    00008  ******************************************************************************
    00009  * Copyright (c) 1999, Frank Warmerdam
    00010  *
    00011  * Permission is hereby granted, free of charge, to any person obtaining a
    00012  * copy of this software and associated documentation files (the "Software"),
    00013  * to deal in the Software without restriction, including without limitation
    00014  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    00015  * and/or sell copies of the Software, and to permit persons to whom the
    00016  * Software is furnished to do so, subject to the following conditions:
    00017  *
    00018  * The above copyright notice and this permission notice shall be included
    00019  * in all copies or substantial portions of the Software.
    00020  *
    00021  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    00022  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    00023  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    00024  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    00025  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    00026  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    00027  * DEALINGS IN THE SOFTWARE.
    00028  ******************************************************************************
    00029  *
    00030  * $Log: gdal_misc_cpp-source.html,v $
    00030  * Revision 1.8  2001/07/05 13:24:08  warmerda
    00030  * *** empty log message ***
    00030  *
    00031  * Revision 1.23  2001/05/01 18:09:25  warmerda
    00032  * added GDALReadWorldFile()
    00033  *
    00034  * Revision 1.22  2000/12/04 20:45:14  warmerda
    00035  * removed unused variable.
    00036  *
    00037  * Revision 1.21  2000/10/06 15:22:49  warmerda
    00038  * added GDALDataTypeUnion
    00039  *
    00040  * Revision 1.20  2000/08/18 15:24:48  warmerda
    00041  * added GDALTermProgress
    00042  *
    00043  * Revision 1.19  2000/08/09 16:25:42  warmerda
    00044  * don't crash if block is null
    00045  *
    00046  * Revision 1.18  2000/07/11 14:35:43  warmerda
    00047  * added documentation
    00048  *
    00049  * Revision 1.17  2000/07/05 17:53:33  warmerda
    00050  * Removed unused code related to nXCheck.
    00051  *
    00052  * Revision 1.16  2000/06/27 17:21:26  warmerda
    00053  * added GDALGetRasterSampleOverview
    00054  *
    00055  * Revision 1.15  2000/06/26 22:17:49  warmerda
    00056  * added scaled progress support
    00057  *
    00058  * Revision 1.14  2000/06/05 17:24:05  warmerda
    00059  * added real complex support
    00060  *
    00061  * Revision 1.13  2000/04/21 21:55:32  warmerda
    00062  * made more robust if block read fails
    00063  *
    00064  * Revision 1.12  2000/04/17 20:59:40  warmerda
    00065  * Removed printf.
    00066  *
    00067  * Revision 1.11  2000/04/17 20:59:14  warmerda
    00068  * fixed sampling bug
    00069  *
    00070  * Revision 1.10  2000/03/31 13:41:45  warmerda
    00071  * added gcp support functions
    00072  *
    00073  * Revision 1.9  2000/03/24 00:09:19  warmerda
    00074  * added sort-of random sampling
    00075  *
    00076  * Revision 1.8  2000/03/23 16:53:21  warmerda
    00077  * use overviews for approximate min/max
    00078  *
    00079  * Revision 1.7  2000/03/09 23:21:44  warmerda
    00080  * added GDALDummyProgress
    00081  *
    00082  * Revision 1.6  2000/03/06 21:59:44  warmerda
    00083  * added min/max calculate
    00084  *
    00085  * Revision 1.5  2000/03/06 02:20:15  warmerda
    00086  * added getname functions for colour interpretations
    00087  *
    00088  * Revision 1.4  1999/07/23 19:35:47  warmerda
    00089  * added GDALGetDataTypeName
    00090  *
    00091  * Revision 1.3  1999/05/17 02:00:45  vgough
    00092  * made pure_virtual C linkage
    00093  *
    00094  * Revision 1.2  1999/05/16 19:32:13  warmerda
    00095  * Added __pure_virtual.
    00096  *
    00097  * Revision 1.1  1998/12/06 02:50:16  warmerda
    00098  * New
    00099  *
    00100  */
    00101
    00102 #include "gdal_priv.h"
    00103 #include "cpl_string.h"
    00104
    00105 /************************************************************************/
    00106 /*                           __pure_virtual()                           */
    00107 /*                                                                      */
    00108 /*      The following is a gross hack to remove the last remaining      */
    00109 /*      dependency on the GNU C++ standard library.                     */
    00110 /************************************************************************/
    00111
    00112 #ifdef __GNUC__
    00113
    00114 extern "C"
    00115 void __pure_virtual()
    00116
    00117 {
    00118 }
    00119
    00120 #endif
    00121
    00122 /************************************************************************/
    00123 /*                         GDALDataTypeUnion()                          */
    00124 /************************************************************************/
    00125
    00136 GDALDataType GDALDataTypeUnion( GDALDataType eType1, GDALDataType eType2 )
    00137
    00138 {
    00139     int         bFloating, bComplex, nBits, bSigned;
    00140
    00141     bComplex = GDALDataTypeIsComplex(eType1) | GDALDataTypeIsComplex(eType2);
    00142
    00143     switch( eType1 )
    00144     {
    00145       case GDT_Byte:
    00146         nBits = 8;
    00147         bSigned = FALSE;
    00148         bFloating = FALSE;
    00149         break;
    00150
    00151       case GDT_Int16:
    00152       case GDT_CInt16:
    00153         nBits = 16;
    00154         bSigned = TRUE;
    00155         bFloating = FALSE;
    00156         break;
    00157
    00158       case GDT_UInt16:
    00159         nBits = 16;
    00160         bSigned = FALSE;
    00161         bFloating = FALSE;
    00162         break;
    00163
    00164       case GDT_Int32:
    00165       case GDT_CInt32:
    00166         nBits = 32;
    00167         bSigned = TRUE;
    00168         bFloating = FALSE;
    00169         break;
    00170
    00171       case GDT_UInt32:
    00172         nBits = 32;
    00173         bSigned = FALSE;
    00174         bFloating = FALSE;
    00175         break;
    00176
    00177       case GDT_Float32:
    00178       case GDT_CFloat32:
    00179         nBits = 32;
    00180         bSigned = TRUE;
    00181         bFloating = TRUE;
    00182         break;
    00183
    00184       case GDT_Float64:
    00185       case GDT_CFloat64:
    00186         nBits = 64;
    00187         bSigned = TRUE;
    00188         bFloating = TRUE;
    00189         break;
    00190
    00191       default:
    00192         CPLAssert( FALSE );
    00193         return GDT_Unknown;
    00194     }
    00195
    00196     switch( eType2 )
    00197     {
    00198       case GDT_Byte:
    00199         break;
    00200
    00201       case GDT_Int16:
    00202         nBits = MAX(nBits,16);
    00203         bSigned = TRUE;
    00204         break;
    00205
    00206       case GDT_UInt16:
    00207         nBits = MAX(nBits,16);
    00208         break;
    00209
    00210       case GDT_Int32:
    00211       case GDT_CInt32:
    00212         nBits = MAX(nBits,32);
    00213         bSigned = TRUE;
    00214         break;
    00215
    00216       case GDT_UInt32:
    00217         nBits = MAX(nBits,32);
    00218         break;
    00219
    00220       case GDT_Float32:
    00221       case GDT_CFloat32:
    00222         nBits = MAX(nBits,32);
    00223         bSigned = TRUE;
    00224         bFloating = TRUE;
    00225         break;
    00226
    00227       case GDT_Float64:
    00228       case GDT_CFloat64:
    00229         nBits = MAX(nBits,64);
    00230         bSigned = TRUE;
    00231         bFloating = TRUE;
    00232         break;
    00233
    00234       default:
    00235         CPLAssert( FALSE );
    00236         return GDT_Unknown;
    00237     }
    00238
    00239     if( nBits == 8 )
    00240         return GDT_Byte;
    00241     else if( nBits == 16 && bComplex )
    00242         return GDT_CInt16;
    00243     else if( nBits == 16 && bSigned )
    00244         return GDT_Int16;
    00245     else if( nBits == 16 && !bSigned )
    00246         return GDT_UInt16;
    00247     else if( nBits == 32 && bFloating && bComplex )
    00248         return GDT_CFloat32;
    00249     else if( nBits == 32 && bFloating )
    00250         return GDT_Float32;
    00251     else if( nBits == 32 && bComplex )
    00252         return GDT_CInt32;
    00253     else if( nBits == 32 && bSigned )
    00254         return GDT_Int32;
    00255     else if( nBits == 32 && !bSigned )
    00256         return GDT_UInt32;
    00257     else if( nBits == 64 && bComplex )
    00258         return GDT_CFloat64;
    00259     else
    00260         return GDT_Float64;
    00261 }
    00262
    00263
    00264 /************************************************************************/
    00265 /*                        GDALGetDataTypeSize()                         */
    00266 /************************************************************************/
    00267 int GDALGetDataTypeSize( GDALDataType eDataType )
    00268
    00269 {
    00270     switch( eDataType )
    00271     {
    00272       case GDT_Byte:
    00273         return 8;
    00274
    00275       case GDT_UInt16:
    00276       case GDT_Int16:
    00277         return 16;
    00278
    00279       case GDT_UInt32:
    00280       case GDT_Int32:
    00281       case GDT_Float32:
    00282       case GDT_CInt16:
    00283         return 32;
    00284
    00285       case GDT_Float64:
    00286       case GDT_CInt32:
    00287       case GDT_CFloat32:
    00288         return 64;
    00289
    00290       case GDT_CFloat64:
    00291         return 128;
    00292
    00293       default:
    00294         CPLAssert( FALSE );
    00295         return 0;
    00296     }
    00297 }
    00298
    00299 /************************************************************************/
    00300 /*                       GDALDataTypeIsComplex()                        */
    00301 /************************************************************************/
    00302
    00303 int GDALDataTypeIsComplex( GDALDataType eDataType )
    00304
    00305 {
    00306     switch( eDataType )
    00307     {
    00308       case GDT_CInt16:
    00309       case GDT_CInt32:
    00310       case GDT_CFloat32:
    00311       case GDT_CFloat64:
    00312         return TRUE;
    00313
    00314       default:
    00315         return FALSE;
    00316     }
    00317 }
    00318
    00319 /************************************************************************/
    00320 /*                        GDALGetDataTypeName()                         */
    00321 /************************************************************************/
    00322
    00323 const char *GDALGetDataTypeName( GDALDataType eDataType )
    00324
    00325 {
    00326     switch( eDataType )
    00327     {
    00328       case GDT_Byte:
    00329         return "Byte";
    00330
    00331       case GDT_UInt16:
    00332         return "UInt16";
    00333
    00334       case GDT_Int16:
    00335         return "Int16";
    00336
    00337       case GDT_UInt32:
    00338         return "UInt32";
    00339
    00340       case GDT_Int32:
    00341         return "Int32";
    00342
    00343       case GDT_Float32:
    00344         return "Float32";
    00345
    00346       case GDT_Float64:
    00347         return "Float64";
    00348
    00349       case GDT_CInt16:
    00350         return "CInt16";
    00351
    00352       case GDT_CInt32:
    00353         return "CInt32";
    00354
    00355       case GDT_CFloat32:
    00356         return "CFloat32";
    00357
    00358       case GDT_CFloat64:
    00359         return "CFloat64";
    00360
    00361       default:
    00362         return NULL;
    00363     }
    00364 }
    00365
    00366 /************************************************************************/
    00367 /*                  GDALGetPaletteInterpretationName()                  */
    00368 /************************************************************************/
    00369
    00370 const char *GDALGetPaletteInterpretationName( GDALPaletteInterp eInterp )
    00371
    00372 {
    00373     switch( eInterp )
    00374     {
    00375       case GPI_Gray:
    00376         return "Gray";
    00377
    00378       case GPI_RGB:
    00379         return "RGB";
    00380
    00381       case GPI_CMYK:
    00382         return "CMYK";
    00383
    00384       case GPI_HLS:
    00385         return "HLS";
    00386
    00387       default:
    00388         return "Unknown";
    00389     }
    00390 }
    00391
    00392 /************************************************************************/
    00393 /*                   GDALGetColorInterpretationName()                   */
    00394 /************************************************************************/
    00395
    00396 const char *GDALGetColorInterpretationName( GDALColorInterp eInterp )
    00397
    00398 {
    00399     switch( eInterp )
    00400     {
    00401       case GCI_Undefined:
    00402         return "Undefined";
    00403
    00404       case GCI_GrayIndex:
    00405         return "Gray";
    00406
    00407       case GCI_PaletteIndex:
    00408         return "Palette";
    00409
    00410       case GCI_RedBand:
    00411         return "Red";
    00412
    00413       case GCI_GreenBand:
    00414         return "Green";
    00415
    00416       case GCI_BlueBand:
    00417         return "Blue";
    00418
    00419       case GCI_AlphaBand:
    00420         return "Alpha";
    00421
    00422       case GCI_HueBand:
    00423         return "Hue";
    00424
    00425       case GCI_SaturationBand:
    00426         return "Saturation";
    00427
    00428       case GCI_LightnessBand:
    00429         return "Lightness";
    00430
    00431       case GCI_CyanBand:
    00432         return "Cyan";
    00433
    00434       case GCI_MagentaBand:
    00435         return "Magenta";
    00436
    00437       case GCI_YellowBand:
    00438         return "Yellow";
    00439
    00440       case GCI_BlackBand:
    00441         return "Black";
    00442
    00443       default:
    00444         return "Unknown";
    00445     }
    00446 }
    00447
    00448 /************************************************************************/
    00449 /*                      GDALComputeRasterMinMax()                       */
    00450 /************************************************************************/
    00451
    00470 void GDALComputeRasterMinMax( GDALRasterBandH hBand, int bApproxOK,
    00471                               double adfMinMax[2] )
    00472
    00473 {
    00474     double       dfMin=0.0, dfMax=0.0;
    00475     GDALRasterBand *poBand;
    00476
    00477 /* -------------------------------------------------------------------- */
    00478 /*      Does the driver already know the min/max?                       */
    00479 /* -------------------------------------------------------------------- */
    00480     if( bApproxOK )
    00481     {
    00482         int          bSuccessMin, bSuccessMax;
    00483
    00484         dfMin = GDALGetRasterMinimum( hBand, &bSuccessMin );
    00485         dfMax = GDALGetRasterMaximum( hBand, &bSuccessMax );
    00486
    00487         if( bSuccessMin && bSuccessMax )
    00488         {
    00489             adfMinMax[0] = dfMin;
    00490             adfMinMax[1] = dfMax;
    00491             return;
    00492         }
    00493     }
    00494
    00495 /* -------------------------------------------------------------------- */
    00496 /*      If we have overview bands, use them for min/max.                */
    00497 /* -------------------------------------------------------------------- */
    00498     if( bApproxOK )
    00499         poBand = (GDALRasterBand *) GDALGetRasterSampleOverview( hBand, 2500 );
    00500     else
    00501         poBand = (GDALRasterBand *) hBand;
    00502
    00503 /* -------------------------------------------------------------------- */
    00504 /*      Figure out the ratio of blocks we will read to get an           */
    00505 /*      approximate value.                                              */
    00506 /* -------------------------------------------------------------------- */
    00507     int         nBlockXSize, nBlockYSize;
    00508     int         nBlocksPerRow, nBlocksPerColumn;
    00509     int         nSampleRate;
    00510     int         bGotNoDataValue, bFirstValue = TRUE;
    00511     double      dfNoDataValue;
    00512
    00513     dfNoDataValue = poBand->GetNoDataValue( &bGotNoDataValue );
    00514
    00515     poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
    00516     nBlocksPerRow = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
    00517     nBlocksPerColumn = (poBand->GetYSize() + nBlockYSize - 1) / nBlockYSize;
    00518
    00519     if( bApproxOK )
    00520         nSampleRate =
    00521             (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn));
    00522     else
    00523         nSampleRate = 1;
    00524
    00525     for( int iSampleBlock = 0;
    00526          iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
    00527          iSampleBlock += nSampleRate )
    00528     {
    00529         double dfValue = 0.0;
    00530         int  iXBlock, iYBlock, nXCheck, nYCheck;
    00531         GDALRasterBlock *poBlock;
    00532
    00533         iYBlock = iSampleBlock / nBlocksPerRow;
    00534         iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
    00535
    00536         poBlock = poBand->GetBlockRef( iXBlock, iYBlock );
    00537         if( poBlock == NULL )
    00538             continue;
    00539
    00540         if( (iXBlock+1) * nBlockXSize > poBand->GetXSize() )
    00541             nXCheck = poBand->GetXSize() - iXBlock * nBlockXSize;
    00542         else
    00543             nXCheck = nBlockXSize;
    00544
    00545         if( (iYBlock+1) * nBlockYSize > poBand->GetYSize() )
    00546             nYCheck = poBand->GetYSize() - iYBlock * nBlockYSize;
    00547         else
    00548             nYCheck = nBlockYSize;
    00549
    00550         /* this isn't the fastest way to do this, but is easier for now */
    00551         for( int iY = 0; iY < nYCheck; iY++ )
    00552         {
    00553             for( int iX = 0; iX < nXCheck; iX++ )
    00554             {
    00555                 int    iOffset = iX + iY * nBlockXSize;
    00556
    00557                 switch( poBlock->GetDataType() )
    00558                 {
    00559                   case GDT_Byte:
    00560                     dfValue = ((GByte *) poBlock->GetDataRef())[iOffset];
    00561                     break;
    00562                   case GDT_UInt16:
    00563                     dfValue = ((GUInt16 *) poBlock->GetDataRef())[iOffset];
    00564                     break;
    00565                   case GDT_Int16:
    00566                     dfValue = ((GInt16 *) poBlock->GetDataRef())[iOffset];
    00567                     break;
    00568                   case GDT_UInt32:
    00569                     dfValue = ((GUInt32 *) poBlock->GetDataRef())[iOffset];
    00570                     break;
    00571                   case GDT_Int32:
    00572                     dfValue = ((GInt32 *) poBlock->GetDataRef())[iOffset];
    00573                     break;
    00574                   case GDT_Float32:
    00575                     dfValue = ((float *) poBlock->GetDataRef())[iOffset];
    00576                     break;
    00577                   case GDT_Float64:
    00578                     dfValue = ((double *) poBlock->GetDataRef())[iOffset];
    00579                     break;
    00580                   case GDT_CInt16:
    00581                     dfValue = ((GInt16 *) poBlock->GetDataRef())[iOffset*2];
    00582                     break;
    00583                   case GDT_CInt32:
    00584                     dfValue = ((GInt32 *) poBlock->GetDataRef())[iOffset*2];
    00585                     break;
    00586                   case GDT_CFloat32:
    00587                     dfValue = ((float *) poBlock->GetDataRef())[iOffset*2];
    00588                     break;
    00589                   case GDT_CFloat64:
    00590                     dfValue = ((double *) poBlock->GetDataRef())[iOffset*2];
    00591                     break;
    00592                   default:
    00593                     CPLAssert( FALSE );
    00594                 }
    00595
    00596                 if( bGotNoDataValue && dfValue == dfNoDataValue )
    00597                     continue;
    00598
    00599                 if( bFirstValue )
    00600                 {
    00601                     dfMin = dfMax = dfValue;
    00602                     bFirstValue = FALSE;
    00603                 }
    00604                 else
    00605                 {
    00606                     dfMin = MIN(dfMin,dfValue);
    00607                     dfMax = MAX(dfMax,dfValue);
    00608                 }
    00609             }
    00610         }
    00611     }
    00612
    00613     adfMinMax[0] = dfMin;
    00614     adfMinMax[1] = dfMax;
    00615 }
    00616
    00617 /************************************************************************/
    00618 /*                         GDALDummyProgress()                          */
    00619 /************************************************************************/
    00620
    00685 int GDALDummyProgress( double, const char *, void * )
    00686
    00687 {
    00688     return TRUE;
    00689 }
    00690
    00691 /************************************************************************/
    00692 /*                         GDALScaledProgress()                         */
    00693 /************************************************************************/
    00694 typedef struct {
    00695     GDALProgressFunc pfnProgress;
    00696     void *pData;
    00697     double dfMin;
    00698     double dfMax;
    00699 } GDALScaledProgressInfo;
    00700
    00701 int GDALScaledProgress( double dfComplete, const char *pszMessage,
    00702                         void *pData )
    00703
    00704 {
    00705     GDALScaledProgressInfo *psInfo = (GDALScaledProgressInfo *) pData;
    00706
    00707     return psInfo->pfnProgress( dfComplete * (psInfo->dfMax - psInfo->dfMin)
    00708                                 + psInfo->dfMin,
    00709                                 pszMessage, psInfo->pData );
    00710 }
    00711
    00712 /************************************************************************/
    00713 /*                      GDALCreateScaledProgress()                      */
    00714 /************************************************************************/
    00715
    00716 void *GDALCreateScaledProgress( double dfMin, double dfMax,
    00717                                 GDALProgressFunc pfnProgress,
    00718                                 void * pData )
    00719
    00720 {
    00721     GDALScaledProgressInfo *psInfo;
    00722
    00723     psInfo = (GDALScaledProgressInfo *)
    00724         CPLCalloc(sizeof(GDALScaledProgressInfo),1);
    00725
    00726     if( ABS(dfMin-dfMax) < 0.0000001 )
    00727         dfMax = dfMin + 0.01;
    00728
    00729     psInfo->pData = pData;
    00730     psInfo->pfnProgress = pfnProgress;
    00731     psInfo->dfMin = dfMin;
    00732     psInfo->dfMax = dfMax;
    00733
    00734     return (void *) psInfo;
    00735 }
    00736
    00737 /************************************************************************/
    00738 /*                     GDALDestroyScaledProgress()                      */
    00739 /************************************************************************/
    00740
    00741 void GDALDestroyScaledProgress( void * pData )
    00742
    00743 {
    00744     CPLFree( pData );
    00745 }
    00746
    00747 /************************************************************************/
    00748 /*                          GDALTermProgress()                          */
    00749 /************************************************************************/
    00750
    00751 int GDALTermProgress( double dfComplete, const char *pszMessage, void * )
    00752
    00753 {
    00754     static double dfLastComplete = -1.0;
    00755
    00756     if( dfLastComplete > dfComplete )
    00757     {
    00758         if( dfLastComplete > 1.0 )
    00759             dfLastComplete = -1.0;
    00760         else
    00761             dfLastComplete = dfComplete;
    00762     }
    00763
    00764     if( floor(dfLastComplete*10) != floor(dfComplete*10) )
    00765     {
    00766         int    nPercent = (int) floor(dfComplete*100);
    00767
    00768         if( nPercent == 0 && pszMessage != NULL )
    00769             fprintf( stdout, "%s:", pszMessage );
    00770
    00771         if( nPercent == 100 )
    00772             fprintf( stdout, "%d - done.\n", (int) floor(dfComplete*100) );
    00773         else
    00774         {
    00775             fprintf( stdout, "%d.", (int) floor(dfComplete*100) );
    00776             fflush( stdout );
    00777         }
    00778     }
    00779     else if( floor(dfLastComplete*30) != floor(dfComplete*30) )
    00780     {
    00781         fprintf( stdout, "." );
    00782         fflush( stdout );
    00783     }
    00784
    00785     dfLastComplete = dfComplete;
    00786
    00787     return TRUE;
    00788 }
    00789
    00790 /************************************************************************/
    00791 /*                    GDALGetRasterSampleOverview()                     */
    00792 /************************************************************************/
    00793
    00809 GDALRasterBandH GDALGetRasterSampleOverview( GDALRasterBandH hBand,
    00810                                              int nDesiredSamples )
    00811
    00812 {
    00813     int     nBestSamples;
    00814     GDALRasterBandH hBestBand = hBand;
    00815
    00816     nBestSamples = GDALGetRasterBandXSize(hBand)
    00817         * GDALGetRasterBandYSize(hBand);
    00818
    00819     for( int iOverview = 0;
    00820          iOverview < GDALGetOverviewCount( hBand );
    00821          iOverview++ )
    00822     {
    00823         GDALRasterBandH hOBand = GDALGetOverview( hBand, iOverview );
    00824         int    nOSamples;
    00825
    00826         nOSamples = GDALGetRasterBandXSize(hOBand)
    00827             * GDALGetRasterBandYSize(hOBand);
    00828
    00829         if( nOSamples < nBestSamples && nOSamples > nDesiredSamples )
    00830         {
    00831             nBestSamples = nOSamples;
    00832             hBestBand = hOBand;
    00833         }
    00834     }
    00835
    00836     return hBestBand;
    00837 }
    00838
    00839 /************************************************************************/
    00840 /*                     GDALGetRandomRasterSample()                      */
    00841 /************************************************************************/
    00842
    00843 int GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
    00844                                float *pafSampleBuf )
    00845
    00846 {
    00847     GDALRasterBand *poBand;
    00848
    00849     poBand = (GDALRasterBand *) GDALGetRasterSampleOverview( hBand, nSamples );
    00850
    00851 /* -------------------------------------------------------------------- */
    00852 /*      Figure out the ratio of blocks we will read to get an           */
    00853 /*      approximate value.                                              */
    00854 /* -------------------------------------------------------------------- */
    00855     int         nBlockXSize, nBlockYSize;
    00856     int         nBlocksPerRow, nBlocksPerColumn;
    00857     int         nSampleRate;
    00858     int         bGotNoDataValue;
    00859     double      dfNoDataValue;
    00860     int         nActualSamples = 0;
    00861     int         nBlockSampleRate;
    00862
    00863     dfNoDataValue = poBand->GetNoDataValue( &bGotNoDataValue );
    00864
    00865     poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
    00866     nBlocksPerRow = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
    00867     nBlocksPerColumn = (poBand->GetYSize() + nBlockYSize - 1) / nBlockYSize;
    00868
    00869     nSampleRate =
    00870         (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn)-2.0);
    00871
    00872     if( nSampleRate == nBlocksPerRow && nSampleRate > 1 )
    00873         nSampleRate--;
    00874
    00875     nBlockSampleRate = MAX(1,(nBlockXSize * nBlockYSize) /
    00876         (nSamples / (nBlocksPerRow*nBlocksPerColumn / nSampleRate)));
    00877
    00878     for( int iSampleBlock = 0;
    00879          iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
    00880          iSampleBlock += nSampleRate )
    00881     {
    00882         double dfValue = 0.0;
    00883         int  iXBlock, iYBlock, iOffset;
    00884         GDALRasterBlock *poBlock;
    00885
    00886         iYBlock = iSampleBlock / nBlocksPerRow;
    00887         iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
    00888
    00889         poBlock = poBand->GetBlockRef( iXBlock, iYBlock );
    00890         if( poBlock == NULL )
    00891             continue;
    00892
    00893         /* this isn't the fastest way to do this, but is easier for now */
    00894         for( iOffset = nBlockXSize*nBlockYSize-1;
    00895              iOffset >= 0 && nActualSamples < nSamples;
    00896              iOffset -= nBlockSampleRate )
    00897         {
    00898             switch( poBlock->GetDataType() )
    00899             {
    00900               case GDT_Byte:
    00901                 dfValue = ((GByte *) poBlock->GetDataRef())[iOffset];
    00902                 break;
    00903               case GDT_UInt16:
    00904                 dfValue = ((GUInt16 *) poBlock->GetDataRef())[iOffset];
    00905                 break;
    00906               case GDT_Int16:
    00907                 dfValue = ((GInt16 *) poBlock->GetDataRef())[iOffset];
    00908                 break;
    00909               case GDT_UInt32:
    00910                 dfValue = ((GUInt32 *) poBlock->GetDataRef())[iOffset];
    00911                 break;
    00912               case GDT_Int32:
    00913                 dfValue = ((GInt32 *) poBlock->GetDataRef())[iOffset];
    00914                 break;
    00915               case GDT_Float32:
    00916                 dfValue = ((float *) poBlock->GetDataRef())[iOffset];
    00917                 break;
    00918               case GDT_Float64:
    00919                 dfValue = ((double *) poBlock->GetDataRef())[iOffset];
    00920                 break;
    00921               case GDT_CInt16:
    00922                 dfValue = ((GInt16 *) poBlock->GetDataRef())[iOffset*2];
    00923                 break;
    00924               case GDT_CInt32:
    00925                 dfValue = ((GInt32 *) poBlock->GetDataRef())[iOffset*2];
    00926                 break;
    00927               case GDT_CFloat32:
    00928                 dfValue = ((float *) poBlock->GetDataRef())[iOffset*2];
    00929                 break;
    00930               case GDT_CFloat64:
    00931                 dfValue = ((double *) poBlock->GetDataRef())[iOffset*2];
    00932                 break;
    00933               default:
    00934                 CPLAssert( FALSE );
    00935             }
    00936
    00937             if( bGotNoDataValue && dfValue == dfNoDataValue )
    00938                 continue;
    00939
    00940             pafSampleBuf[nActualSamples++] = dfValue;
    00941         }
    00942     }
    00943
    00944     return nActualSamples;
    00945 }
    00946
    00947 /************************************************************************/
    00948 /*                            GDALInitGCPs()                            */
    00949 /************************************************************************/
    00950
    00951 void GDALInitGCPs( int nCount, GDAL_GCP * psGCP )
    00952
    00953 {
    00954     for( int iGCP = 0; iGCP < nCount; iGCP++ )
    00955     {
    00956         memset( psGCP, 0, sizeof(GDAL_GCP) );
    00957         psGCP->pszId = CPLStrdup("");
    00958         psGCP->pszInfo = CPLStrdup("");
    00959         psGCP++;
    00960     }
    00961 }
    00962
    00963 /************************************************************************/
    00964 /*                           GDALDeinitGCPs()                           */
    00965 /************************************************************************/
    00966
    00967 void GDALDeinitGCPs( int nCount, GDAL_GCP * psGCP )
    00968
    00969 {
    00970     for( int iGCP = 0; iGCP < nCount; iGCP++ )
    00971     {
    00972         CPLFree( psGCP->pszId );
    00973         CPLFree( psGCP->pszInfo );
    00974         psGCP++;
    00975     }
    00976 }
    00977
    00978 /************************************************************************/
    00979 /*                         GDALDuplicateGCPs()                          */
    00980 /************************************************************************/
    00981
    00982 GDAL_GCP *GDALDuplicateGCPs( int nCount, const GDAL_GCP *pasGCPList )
    00983
    00984 {
    00985     GDAL_GCP    *pasReturn;
    00986
    00987     pasReturn = (GDAL_GCP *) CPLMalloc(sizeof(GDAL_GCP) * nCount);
    00988     GDALInitGCPs( nCount, pasReturn );
    00989
    00990     for( int iGCP = 0; iGCP < nCount; iGCP++ )
    00991     {
    00992         CPLFree( pasReturn[iGCP].pszId );
    00993         pasReturn[iGCP].pszId = CPLStrdup( pasGCPList[iGCP].pszId );
    00994
    00995         CPLFree( pasReturn[iGCP].pszInfo );
    00996         pasReturn[iGCP].pszInfo = CPLStrdup( pasGCPList[iGCP].pszInfo );
    00997
    00998         pasReturn[iGCP].dfGCPPixel = pasGCPList[iGCP].dfGCPPixel;
    00999         pasReturn[iGCP].dfGCPLine = pasGCPList[iGCP].dfGCPLine;
    01000         pasReturn[iGCP].dfGCPX = pasGCPList[iGCP].dfGCPX;
    01001         pasReturn[iGCP].dfGCPY = pasGCPList[iGCP].dfGCPY;
    01002         pasReturn[iGCP].dfGCPZ = pasGCPList[iGCP].dfGCPZ;
    01003     }
    01004
    01005     return pasReturn;
    01006 }
    01007
    01008 /************************************************************************/
    01009 /*                         GDALReadWorldFile()                          */
    01010 /*                                                                      */
    01011 /*      Helper function for translator implementators wanting           */
    01012 /*      support for ESRI world files.                                   */
    01013 /************************************************************************/
    01014
    01015 int GDALReadWorldFile( const char * pszBaseFilename, const char *pszExtension,
    01016                        double *padfGeoTransform )
    01017
    01018 {
    01019     const char  *pszTFW;
    01020     char        szExtUpper[32], szExtLower[32];
    01021     int         i;
    01022     FILE        *fpTFW;
    01023     char        **papszLines;
    01024
    01025     if( *pszExtension == '.' )
    01026         pszExtension++;
    01027
    01028 /* -------------------------------------------------------------------- */
    01029 /*      Generate upper and lower case versions of the extension.        */
    01030 /* -------------------------------------------------------------------- */
    01031     strcpy( szExtUpper, pszExtension );
    01032     strcpy( szExtLower, pszExtension );
    01033
    01034     for( i = 0; szExtUpper[i] != '\0'; i++ )
    01035     {
    01036         if( szExtUpper[i] >= 'a' && szExtUpper[i] <= 'z' )
    01037             szExtUpper[i] = szExtUpper[i] - 'a' + 'A';
    01038         if( szExtLower[i] >= 'A' && szExtLower[i] <= 'Z' )
    01039             szExtLower[i] = szExtLower[i] - 'A' + 'a';
    01040     }
    01041
    01042 /* -------------------------------------------------------------------- */
    01043 /*      Try lower case, then upper case.                                */
    01044 /* -------------------------------------------------------------------- */
    01045     pszTFW = CPLResetExtension( pszBaseFilename, szExtLower );
    01046
    01047     fpTFW = VSIFOpen( pszTFW, "rt" );
    01048
    01049 #ifndef WIN32
    01050     if( fpTFW == NULL )
    01051     {
    01052         pszTFW = CPLResetExtension( pszBaseFilename, szExtUpper );
    01053         fpTFW = VSIFOpen( pszTFW, "rt" );
    01054     }
    01055 #endif
    01056
    01057     if( fpTFW == NULL )
    01058         return FALSE;
    01059
    01060     VSIFClose( fpTFW );
    01061
    01062 /* -------------------------------------------------------------------- */
    01063 /*      We found the file, now load and parse it.                       */
    01064 /* -------------------------------------------------------------------- */
    01065     papszLines = CSLLoad( pszTFW );
    01066     if( CSLCount(papszLines) >= 6
    01067         && atof(papszLines[0]) != 0.0
    01068         && atof(papszLines[3]) != 0.0 )
    01069     {
    01070         padfGeoTransform[0] = atof(papszLines[4]);
    01071         padfGeoTransform[1] = atof(papszLines[0]);
    01072         padfGeoTransform[2] = atof(papszLines[2]);
    01073         padfGeoTransform[3] = atof(papszLines[5]);
    01074         padfGeoTransform[4] = atof(papszLines[1]);
    01075         padfGeoTransform[5] = atof(papszLines[3]);
    01076
    01077         // correct for center of pixel vs. top left of pixel
    01078         padfGeoTransform[0] -= 0.5 * padfGeoTransform[1];
    01079         padfGeoTransform[0] -= 0.5 * padfGeoTransform[2];
    01080         padfGeoTransform[3] -= 0.5 * padfGeoTransform[4];
    01081         padfGeoTransform[3] -= 0.5 * padfGeoTransform[5];
    01082
    01083         CSLDestroy(papszLines);
    01084
    01085         return TRUE;
    01086     }
    01087     else
    01088     {
    01089         CPLDebug( "GDAL",
    01090                   "GDALReadWorldFile(%s) found file, but it was corrupt.",
    01091                   pszTFW );
    01092         CSLDestroy(papszLines);
    01093         return FALSE;
    01094     }
    01095 }
    01096
    01097