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.3 2000/10/20 20:21:34 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.3  2000/10/20 20:21:34  warmerda
    00030  * *** empty log message ***
    00030  *
    00031  * Revision 1.21  2000/10/06 15:22:49  warmerda
    00032  * added GDALDataTypeUnion
    00033  *
    00034  * Revision 1.20  2000/08/18 15:24:48  warmerda
    00035  * added GDALTermProgress
    00036  *
    00037  * Revision 1.19  2000/08/09 16:25:42  warmerda
    00038  * don't crash if block is null
    00039  *
    00040  * Revision 1.18  2000/07/11 14:35:43  warmerda
    00041  * added documentation
    00042  *
    00043  * Revision 1.17  2000/07/05 17:53:33  warmerda
    00044  * Removed unused code related to nXCheck.
    00045  *
    00046  * Revision 1.16  2000/06/27 17:21:26  warmerda
    00047  * added GDALGetRasterSampleOverview
    00048  *
    00049  * Revision 1.15  2000/06/26 22:17:49  warmerda
    00050  * added scaled progress support
    00051  *
    00052  * Revision 1.14  2000/06/05 17:24:05  warmerda
    00053  * added real complex support
    00054  *
    00055  * Revision 1.13  2000/04/21 21:55:32  warmerda
    00056  * made more robust if block read fails
    00057  *
    00058  * Revision 1.12  2000/04/17 20:59:40  warmerda
    00059  * Removed printf.
    00060  *
    00061  * Revision 1.11  2000/04/17 20:59:14  warmerda
    00062  * fixed sampling bug
    00063  *
    00064  * Revision 1.10  2000/03/31 13:41:45  warmerda
    00065  * added gcp support functions
    00066  *
    00067  * Revision 1.9  2000/03/24 00:09:19  warmerda
    00068  * added sort-of random sampling
    00069  *
    00070  * Revision 1.8  2000/03/23 16:53:21  warmerda
    00071  * use overviews for approximate min/max
    00072  *
    00073  * Revision 1.7  2000/03/09 23:21:44  warmerda
    00074  * added GDALDummyProgress
    00075  *
    00076  * Revision 1.6  2000/03/06 21:59:44  warmerda
    00077  * added min/max calculate
    00078  *
    00079  * Revision 1.5  2000/03/06 02:20:15  warmerda
    00080  * added getname functions for colour interpretations
    00081  *
    00082  * Revision 1.4  1999/07/23 19:35:47  warmerda
    00083  * added GDALGetDataTypeName
    00084  *
    00085  * Revision 1.3  1999/05/17 02:00:45  vgough
    00086  * made pure_virtual C linkage
    00087  *
    00088  * Revision 1.2  1999/05/16 19:32:13  warmerda
    00089  * Added __pure_virtual.
    00090  *
    00091  * Revision 1.1  1998/12/06 02:50:16  warmerda
    00092  * New
    00093  *
    00094  */
    00095
    00096 #include "gdal_priv.h"
    00097
    00098 /************************************************************************/
    00099 /*                           __pure_virtual()                           */
    00100 /*                                                                      */
    00101 /*      The following is a gross hack to remove the last remaining      */
    00102 /*      dependency on the GNU C++ standard library.                     */
    00103 /************************************************************************/
    00104
    00105 #ifdef __GNUC__
    00106
    00107 extern "C"
    00108 void __pure_virtual()
    00109
    00110 {
    00111 }
    00112
    00113 #endif
    00114
    00115 /************************************************************************/
    00116 /*                         GDALDataTypeUnion()                          */
    00117 /************************************************************************/
    00118
    00129 GDALDataType GDALDataTypeUnion( GDALDataType eType1, GDALDataType eType2 )
    00130
    00131 {
    00132     int         bFloating, bComplex, nBits, bSigned;
    00133
    00134     bComplex = GDALDataTypeIsComplex(eType1) | GDALDataTypeIsComplex(eType2);
    00135
    00136     switch( eType1 )
    00137     {
    00138       case GDT_Byte:
    00139         nBits = 8;
    00140         bSigned = FALSE;
    00141         bFloating = FALSE;
    00142         break;
    00143
    00144       case GDT_Int16:
    00145       case GDT_CInt16:
    00146         nBits = 16;
    00147         bSigned = TRUE;
    00148         bFloating = FALSE;
    00149         break;
    00150
    00151       case GDT_UInt16:
    00152         nBits = 16;
    00153         bSigned = FALSE;
    00154         bFloating = FALSE;
    00155         break;
    00156
    00157       case GDT_Int32:
    00158       case GDT_CInt32:
    00159         nBits = 32;
    00160         bSigned = TRUE;
    00161         bFloating = FALSE;
    00162         break;
    00163
    00164       case GDT_UInt32:
    00165         nBits = 32;
    00166         bSigned = FALSE;
    00167         bFloating = FALSE;
    00168         break;
    00169
    00170       case GDT_Float32:
    00171       case GDT_CFloat32:
    00172         nBits = 32;
    00173         bSigned = TRUE;
    00174         bFloating = TRUE;
    00175         break;
    00176
    00177       case GDT_Float64:
    00178       case GDT_CFloat64:
    00179         nBits = 64;
    00180         bSigned = TRUE;
    00181         bFloating = TRUE;
    00182         break;
    00183
    00184       default:
    00185         CPLAssert( FALSE );
    00186         return GDT_Unknown;
    00187     }
    00188
    00189     switch( eType2 )
    00190     {
    00191       case GDT_Byte:
    00192         break;
    00193
    00194       case GDT_Int16:
    00195         nBits = MAX(nBits,16);
    00196         bSigned = TRUE;
    00197         break;
    00198
    00199       case GDT_UInt16:
    00200         nBits = MAX(nBits,16);
    00201         break;
    00202
    00203       case GDT_Int32:
    00204       case GDT_CInt32:
    00205         nBits = MAX(nBits,32);
    00206         bSigned = TRUE;
    00207         break;
    00208
    00209       case GDT_UInt32:
    00210         nBits = MAX(nBits,32);
    00211         break;
    00212
    00213       case GDT_Float32:
    00214       case GDT_CFloat32:
    00215         nBits = MAX(nBits,32);
    00216         bSigned = TRUE;
    00217         bFloating = TRUE;
    00218         break;
    00219
    00220       case GDT_Float64:
    00221       case GDT_CFloat64:
    00222         nBits = MAX(nBits,64);
    00223         bSigned = TRUE;
    00224         bFloating = TRUE;
    00225         break;
    00226
    00227       default:
    00228         CPLAssert( FALSE );
    00229         return GDT_Unknown;
    00230     }
    00231
    00232     if( nBits == 8 )
    00233         return GDT_Byte;
    00234     else if( nBits == 16 && bComplex )
    00235         return GDT_CInt16;
    00236     else if( nBits == 16 && bSigned )
    00237         return GDT_Int16;
    00238     else if( nBits == 16 && !bSigned )
    00239         return GDT_UInt16;
    00240     else if( nBits == 32 && bFloating && bComplex )
    00241         return GDT_CFloat32;
    00242     else if( nBits == 32 && bFloating )
    00243         return GDT_Float32;
    00244     else if( nBits == 32 && bComplex )
    00245         return GDT_CInt32;
    00246     else if( nBits == 32 && bSigned )
    00247         return GDT_Int32;
    00248     else if( nBits == 32 && !bSigned )
    00249         return GDT_UInt32;
    00250     else if( nBits == 64 && bComplex )
    00251         return GDT_CFloat64;
    00252     else
    00253         return GDT_Float64;
    00254 }
    00255
    00256
    00257 /************************************************************************/
    00258 /*                        GDALGetDataTypeSize()                         */
    00259 /************************************************************************/
    00260 int GDALGetDataTypeSize( GDALDataType eDataType )
    00261
    00262 {
    00263     switch( eDataType )
    00264     {
    00265       case GDT_Byte:
    00266         return 8;
    00267
    00268       case GDT_UInt16:
    00269       case GDT_Int16:
    00270         return 16;
    00271
    00272       case GDT_UInt32:
    00273       case GDT_Int32:
    00274       case GDT_Float32:
    00275       case GDT_CInt16:
    00276         return 32;
    00277
    00278       case GDT_Float64:
    00279       case GDT_CInt32:
    00280       case GDT_CFloat32:
    00281         return 64;
    00282
    00283       case GDT_CFloat64:
    00284         return 128;
    00285
    00286       default:
    00287         CPLAssert( FALSE );
    00288         return 0;
    00289     }
    00290 }
    00291
    00292 /************************************************************************/
    00293 /*                       GDALDataTypeIsComplex()                        */
    00294 /************************************************************************/
    00295
    00296 int GDALDataTypeIsComplex( GDALDataType eDataType )
    00297
    00298 {
    00299     switch( eDataType )
    00300     {
    00301       case GDT_CInt16:
    00302       case GDT_CInt32:
    00303       case GDT_CFloat32:
    00304       case GDT_CFloat64:
    00305         return TRUE;
    00306
    00307       default:
    00308         return FALSE;
    00309     }
    00310 }
    00311
    00312 /************************************************************************/
    00313 /*                        GDALGetDataTypeName()                         */
    00314 /************************************************************************/
    00315
    00316 const char *GDALGetDataTypeName( GDALDataType eDataType )
    00317
    00318 {
    00319     switch( eDataType )
    00320     {
    00321       case GDT_Byte:
    00322         return "Byte";
    00323
    00324       case GDT_UInt16:
    00325         return "UInt16";
    00326
    00327       case GDT_Int16:
    00328         return "Int16";
    00329
    00330       case GDT_UInt32:
    00331         return "UInt32";
    00332
    00333       case GDT_Int32:
    00334         return "Int32";
    00335
    00336       case GDT_Float32:
    00337         return "Float32";
    00338
    00339       case GDT_Float64:
    00340         return "Float64";
    00341
    00342       case GDT_CInt16:
    00343         return "CInt16";
    00344
    00345       case GDT_CInt32:
    00346         return "CInt32";
    00347
    00348       case GDT_CFloat32:
    00349         return "CFloat32";
    00350
    00351       case GDT_CFloat64:
    00352         return "CFloat64";
    00353
    00354       default:
    00355         return NULL;
    00356     }
    00357 }
    00358
    00359 /************************************************************************/
    00360 /*                  GDALGetPaletteInterpretationName()                  */
    00361 /************************************************************************/
    00362
    00363 const char *GDALGetPaletteInterpretationName( GDALPaletteInterp eInterp )
    00364
    00365 {
    00366     switch( eInterp )
    00367     {
    00368       case GPI_Gray:
    00369         return "Gray";
    00370
    00371       case GPI_RGB:
    00372         return "RGB";
    00373
    00374       case GPI_CMYK:
    00375         return "CMYK";
    00376
    00377       case GPI_HLS:
    00378         return "HLS";
    00379
    00380       default:
    00381         return "Unknown";
    00382     }
    00383 }
    00384
    00385 /************************************************************************/
    00386 /*                   GDALGetColorInterpretationName()                   */
    00387 /************************************************************************/
    00388
    00389 const char *GDALGetColorInterpretationName( GDALColorInterp eInterp )
    00390
    00391 {
    00392     switch( eInterp )
    00393     {
    00394       case GCI_Undefined:
    00395         return "Undefined";
    00396
    00397       case GCI_GrayIndex:
    00398         return "Gray";
    00399
    00400       case GCI_PaletteIndex:
    00401         return "Palette";
    00402
    00403       case GCI_RedBand:
    00404         return "Red";
    00405
    00406       case GCI_GreenBand:
    00407         return "Green";
    00408
    00409       case GCI_BlueBand:
    00410         return "Blue";
    00411
    00412       case GCI_AlphaBand:
    00413         return "Alpha";
    00414
    00415       case GCI_HueBand:
    00416         return "Hue";
    00417
    00418       case GCI_SaturationBand:
    00419         return "Saturation";
    00420
    00421       case GCI_LightnessBand:
    00422         return "Lightness";
    00423
    00424       case GCI_CyanBand:
    00425         return "Cyan";
    00426
    00427       case GCI_MagentaBand:
    00428         return "Magenta";
    00429
    00430       case GCI_YellowBand:
    00431         return "Yellow";
    00432
    00433       case GCI_BlackBand:
    00434         return "Black";
    00435
    00436       default:
    00437         return "Unknown";
    00438     }
    00439 }
    00440
    00441 /************************************************************************/
    00442 /*                      GDALComputeRasterMinMax()                       */
    00443 /************************************************************************/
    00444
    00463 void GDALComputeRasterMinMax( GDALRasterBandH hBand, int bApproxOK,
    00464                               double adfMinMax[2] )
    00465
    00466 {
    00467     double       dfMin=0.0, dfMax=0.0;
    00468     GDALRasterBand *poBand;
    00469
    00470 /* -------------------------------------------------------------------- */
    00471 /*      Does the driver already know the min/max?                       */
    00472 /* -------------------------------------------------------------------- */
    00473     if( bApproxOK )
    00474     {
    00475         int          bSuccessMin, bSuccessMax;
    00476
    00477         dfMin = GDALGetRasterMinimum( hBand, &bSuccessMin );
    00478         dfMax = GDALGetRasterMaximum( hBand, &bSuccessMax );
    00479
    00480         if( bSuccessMin && bSuccessMax )
    00481         {
    00482             adfMinMax[0] = dfMin;
    00483             adfMinMax[1] = dfMax;
    00484             return;
    00485         }
    00486     }
    00487
    00488 /* -------------------------------------------------------------------- */
    00489 /*      If we have overview bands, use them for min/max.                */
    00490 /* -------------------------------------------------------------------- */
    00491     if( bApproxOK )
    00492         poBand = (GDALRasterBand *) GDALGetRasterSampleOverview( hBand, 2500 );
    00493     else
    00494         poBand = (GDALRasterBand *) hBand;
    00495
    00496 /* -------------------------------------------------------------------- */
    00497 /*      Figure out the ratio of blocks we will read to get an           */
    00498 /*      approximate value.                                              */
    00499 /* -------------------------------------------------------------------- */
    00500     int         nBlockXSize, nBlockYSize;
    00501     int         nBlocksPerRow, nBlocksPerColumn;
    00502     int         nSampleRate;
    00503     int         bGotNoDataValue, bFirstValue = TRUE;
    00504     double      dfNoDataValue;
    00505
    00506     dfNoDataValue = poBand->GetNoDataValue( &bGotNoDataValue );
    00507
    00508     poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
    00509     nBlocksPerRow = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
    00510     nBlocksPerColumn = (poBand->GetYSize() + nBlockYSize - 1) / nBlockYSize;
    00511
    00512     if( bApproxOK )
    00513         nSampleRate =
    00514             (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn));
    00515     else
    00516         nSampleRate = 1;
    00517
    00518     for( int iSampleBlock = 0;
    00519          iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
    00520          iSampleBlock += nSampleRate )
    00521     {
    00522         double dfValue = 0.0;
    00523         int  iXBlock, iYBlock, nXCheck, nYCheck;
    00524         GDALRasterBlock *poBlock;
    00525
    00526         iYBlock = iSampleBlock / nBlocksPerRow;
    00527         iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
    00528
    00529         poBlock = poBand->GetBlockRef( iXBlock, iYBlock );
    00530         if( poBlock == NULL )
    00531             continue;
    00532
    00533         if( (iXBlock+1) * nBlockXSize > poBand->GetXSize() )
    00534             nXCheck = poBand->GetXSize() - iXBlock * nBlockXSize;
    00535         else
    00536             nXCheck = nBlockXSize;
    00537
    00538         if( (iYBlock+1) * nBlockYSize > poBand->GetYSize() )
    00539             nYCheck = poBand->GetYSize() - iYBlock * nBlockYSize;
    00540         else
    00541             nYCheck = nBlockYSize;
    00542
    00543         /* this isn't the fastest way to do this, but is easier for now */
    00544         for( int iY = 0; iY < nYCheck; iY++ )
    00545         {
    00546             for( int iX = 0; iX < nXCheck; iX++ )
    00547             {
    00548                 int    iOffset = iX + iY * nBlockXSize;
    00549
    00550                 switch( poBlock->GetDataType() )
    00551                 {
    00552                   case GDT_Byte:
    00553                     dfValue = ((GByte *) poBlock->GetDataRef())[iOffset];
    00554                     break;
    00555                   case GDT_UInt16:
    00556                     dfValue = ((GUInt16 *) poBlock->GetDataRef())[iOffset];
    00557                     break;
    00558                   case GDT_Int16:
    00559                     dfValue = ((GInt16 *) poBlock->GetDataRef())[iOffset];
    00560                     break;
    00561                   case GDT_UInt32:
    00562                     dfValue = ((GUInt32 *) poBlock->GetDataRef())[iOffset];
    00563                     break;
    00564                   case GDT_Int32:
    00565                     dfValue = ((GInt32 *) poBlock->GetDataRef())[iOffset];
    00566                     break;
    00567                   case GDT_Float32:
    00568                     dfValue = ((float *) poBlock->GetDataRef())[iOffset];
    00569                     break;
    00570                   case GDT_Float64:
    00571                     dfValue = ((double *) poBlock->GetDataRef())[iOffset];
    00572                     break;
    00573                   case GDT_CInt16:
    00574                     dfValue = ((GInt16 *) poBlock->GetDataRef())[iOffset*2];
    00575                     break;
    00576                   case GDT_CInt32:
    00577                     dfValue = ((GInt32 *) poBlock->GetDataRef())[iOffset*2];
    00578                     break;
    00579                   case GDT_CFloat32:
    00580                     dfValue = ((float *) poBlock->GetDataRef())[iOffset*2];
    00581                     break;
    00582                   case GDT_CFloat64:
    00583                     dfValue = ((double *) poBlock->GetDataRef())[iOffset*2];
    00584                     break;
    00585                   default:
    00586                     CPLAssert( FALSE );
    00587                 }
    00588
    00589                 if( bGotNoDataValue && dfValue == dfNoDataValue )
    00590                     continue;
    00591
    00592                 if( bFirstValue )
    00593                 {
    00594                     dfMin = dfMax = dfValue;
    00595                     bFirstValue = FALSE;
    00596                 }
    00597                 else
    00598                 {
    00599                     dfMin = MIN(dfMin,dfValue);
    00600                     dfMax = MAX(dfMax,dfValue);
    00601                 }
    00602             }
    00603         }
    00604     }
    00605
    00606     adfMinMax[0] = dfMin;
    00607     adfMinMax[1] = dfMax;
    00608 }
    00609
    00610 /************************************************************************/
    00611 /*                         GDALDummyProgress()                          */
    00612 /************************************************************************/
    00613
    00678 int GDALDummyProgress( double, const char *, void * )
    00679
    00680 {
    00681     return TRUE;
    00682 }
    00683
    00684 /************************************************************************/
    00685 /*                         GDALScaledProgress()                         */
    00686 /************************************************************************/
    00687 typedef struct {
    00688     GDALProgressFunc pfnProgress;
    00689     void *pData;
    00690     double dfMin;
    00691     double dfMax;
    00692 } GDALScaledProgressInfo;
    00693
    00694 int GDALScaledProgress( double dfComplete, const char *pszMessage,
    00695                         void *pData )
    00696
    00697 {
    00698     GDALScaledProgressInfo *psInfo = (GDALScaledProgressInfo *) pData;
    00699
    00700     return psInfo->pfnProgress( dfComplete * (psInfo->dfMax - psInfo->dfMin)
    00701                                 + psInfo->dfMin,
    00702                                 pszMessage, psInfo->pData );
    00703 }
    00704
    00705 /************************************************************************/
    00706 /*                      GDALCreateScaledProgress()                      */
    00707 /************************************************************************/
    00708
    00709 void *GDALCreateScaledProgress( double dfMin, double dfMax,
    00710                                 GDALProgressFunc pfnProgress,
    00711                                 void * pData )
    00712
    00713 {
    00714     GDALScaledProgressInfo *psInfo;
    00715
    00716     psInfo = (GDALScaledProgressInfo *)
    00717         CPLCalloc(sizeof(GDALScaledProgressInfo),1);
    00718
    00719     if( ABS(dfMin-dfMax) < 0.0000001 )
    00720         dfMax = dfMin + 0.01;
    00721
    00722     psInfo->pData = pData;
    00723     psInfo->pfnProgress = pfnProgress;
    00724     psInfo->dfMin = dfMin;
    00725     psInfo->dfMax = dfMax;
    00726
    00727     return (void *) psInfo;
    00728 }
    00729
    00730 /************************************************************************/
    00731 /*                     GDALDestroyScaledProgress()                      */
    00732 /************************************************************************/
    00733
    00734 void GDALDestroyScaledProgress( void * pData )
    00735
    00736 {
    00737     CPLFree( pData );
    00738 }
    00739
    00740 /************************************************************************/
    00741 /*                          GDALTermProgress()                          */
    00742 /************************************************************************/
    00743
    00744 int GDALTermProgress( double dfComplete, const char *pszMessage, void * )
    00745
    00746 {
    00747     static double dfLastComplete = -1.0;
    00748
    00749     if( dfLastComplete > dfComplete )
    00750     {
    00751         if( dfLastComplete > 1.0 )
    00752             dfLastComplete = -1.0;
    00753         else
    00754             dfLastComplete = dfComplete;
    00755     }
    00756
    00757     if( floor(dfLastComplete*10) != floor(dfComplete*10) )
    00758     {
    00759         int    nPercent = (int) floor(dfComplete*100);
    00760
    00761         if( nPercent == 0 && pszMessage != NULL )
    00762             fprintf( stdout, "%s:", pszMessage );
    00763
    00764         if( nPercent == 100 )
    00765             fprintf( stdout, "%d - done.\n", (int) floor(dfComplete*100) );
    00766         else
    00767         {
    00768             fprintf( stdout, "%d.", (int) floor(dfComplete*100) );
    00769             fflush( stdout );
    00770         }
    00771     }
    00772     else if( floor(dfLastComplete*30) != floor(dfComplete*30) )
    00773     {
    00774         fprintf( stdout, "." );
    00775         fflush( stdout );
    00776     }
    00777
    00778     dfLastComplete = dfComplete;
    00779
    00780     return TRUE;
    00781 }
    00782
    00783 /************************************************************************/
    00784 /*                    GDALGetRasterSampleOverview()                     */
    00785 /************************************************************************/
    00786
    00802 GDALRasterBandH GDALGetRasterSampleOverview( GDALRasterBandH hBand,
    00803                                              int nDesiredSamples )
    00804
    00805 {
    00806     int     nBestSamples;
    00807     GDALRasterBandH hBestBand = hBand;
    00808
    00809     nBestSamples = GDALGetRasterBandXSize(hBand)
    00810         * GDALGetRasterBandYSize(hBand);
    00811
    00812     for( int iOverview = 0;
    00813          iOverview < GDALGetOverviewCount( hBand );
    00814          iOverview++ )
    00815     {
    00816         GDALRasterBandH hOBand = GDALGetOverview( hBand, iOverview );
    00817         int    nOSamples;
    00818
    00819         nOSamples = GDALGetRasterBandXSize(hOBand)
    00820             * GDALGetRasterBandYSize(hOBand);
    00821
    00822         if( nOSamples < nBestSamples && nOSamples > nDesiredSamples )
    00823         {
    00824             nBestSamples = nOSamples;
    00825             hBestBand = hOBand;
    00826         }
    00827     }
    00828
    00829     return hBestBand;
    00830 }
    00831
    00832 /************************************************************************/
    00833 /*                     GDALGetRandomRasterSample()                      */
    00834 /************************************************************************/
    00835
    00836 int GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
    00837                                float *pafSampleBuf )
    00838
    00839 {
    00840     GDALRasterBand *poBand;
    00841
    00842     poBand = (GDALRasterBand *) GDALGetRasterSampleOverview( hBand, nSamples );
    00843
    00844 /* -------------------------------------------------------------------- */
    00845 /*      Figure out the ratio of blocks we will read to get an           */
    00846 /*      approximate value.                                              */
    00847 /* -------------------------------------------------------------------- */
    00848     int         nBlockXSize, nBlockYSize;
    00849     int         nBlocksPerRow, nBlocksPerColumn;
    00850     int         nSampleRate;
    00851     int         bGotNoDataValue;
    00852     double      dfNoDataValue;
    00853     int         nActualSamples = 0;
    00854     int         nBlockSampleRate;
    00855
    00856     dfNoDataValue = poBand->GetNoDataValue( &bGotNoDataValue );
    00857
    00858     poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
    00859     nBlocksPerRow = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
    00860     nBlocksPerColumn = (poBand->GetYSize() + nBlockYSize - 1) / nBlockYSize;
    00861
    00862     nSampleRate =
    00863         (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn)-2.0);
    00864
    00865     if( nSampleRate == nBlocksPerRow && nSampleRate > 1 )
    00866         nSampleRate--;
    00867
    00868     nBlockSampleRate = MAX(1,(nBlockXSize * nBlockYSize) /
    00869         (nSamples / (nBlocksPerRow*nBlocksPerColumn / nSampleRate)));
    00870
    00871     for( int iSampleBlock = 0;
    00872          iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
    00873          iSampleBlock += nSampleRate )
    00874     {
    00875         double dfValue = 0.0;
    00876         int  iXBlock, iYBlock, nYCheck, iOffset;
    00877         GDALRasterBlock *poBlock;
    00878
    00879         iYBlock = iSampleBlock / nBlocksPerRow;
    00880         iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
    00881
    00882         poBlock = poBand->GetBlockRef( iXBlock, iYBlock );
    00883         if( poBlock == NULL )
    00884             continue;
    00885
    00886         if( (iYBlock+1) * nBlockYSize > poBand->GetYSize() )
    00887             nYCheck = poBand->GetYSize() - iYBlock * nBlockYSize;
    00888         else
    00889             nYCheck = nBlockYSize;
    00890
    00891         /* this isn't the fastest way to do this, but is easier for now */
    00892         for( iOffset = nBlockXSize*nBlockYSize-1;
    00893              iOffset >= 0 && nActualSamples < nSamples;
    00894              iOffset -= nBlockSampleRate )
    00895         {
    00896             switch( poBlock->GetDataType() )
    00897             {
    00898               case GDT_Byte:
    00899                 dfValue = ((GByte *) poBlock->GetDataRef())[iOffset];
    00900                 break;
    00901               case GDT_UInt16:
    00902                 dfValue = ((GUInt16 *) poBlock->GetDataRef())[iOffset];
    00903                 break;
    00904               case GDT_Int16:
    00905                 dfValue = ((GInt16 *) poBlock->GetDataRef())[iOffset];
    00906                 break;
    00907               case GDT_UInt32:
    00908                 dfValue = ((GUInt32 *) poBlock->GetDataRef())[iOffset];
    00909                 break;
    00910               case GDT_Int32:
    00911                 dfValue = ((GInt32 *) poBlock->GetDataRef())[iOffset];
    00912                 break;
    00913               case GDT_Float32:
    00914                 dfValue = ((float *) poBlock->GetDataRef())[iOffset];
    00915                 break;
    00916               case GDT_Float64:
    00917                 dfValue = ((double *) poBlock->GetDataRef())[iOffset];
    00918                 break;
    00919               case GDT_CInt16:
    00920                 dfValue = ((GInt16 *) poBlock->GetDataRef())[iOffset*2];
    00921                 break;
    00922               case GDT_CInt32:
    00923                 dfValue = ((GInt32 *) poBlock->GetDataRef())[iOffset*2];
    00924                 break;
    00925               case GDT_CFloat32:
    00926                 dfValue = ((float *) poBlock->GetDataRef())[iOffset*2];
    00927                 break;
    00928               case GDT_CFloat64:
    00929                 dfValue = ((double *) poBlock->GetDataRef())[iOffset*2];
    00930                 break;
    00931               default:
    00932                 CPLAssert( FALSE );
    00933             }
    00934
    00935             if( bGotNoDataValue && dfValue == dfNoDataValue )
    00936                 continue;
    00937
    00938             pafSampleBuf[nActualSamples++] = dfValue;
    00939         }
    00940     }
    00941
    00942     return nActualSamples;
    00943 }
    00944
    00945 /************************************************************************/
    00946 /*                            GDALInitGCPs()                            */
    00947 /************************************************************************/
    00948
    00949 void GDALInitGCPs( int nCount, GDAL_GCP * psGCP )
    00950
    00951 {
    00952     for( int iGCP = 0; iGCP < nCount; iGCP++ )
    00953     {
    00954         memset( psGCP, 0, sizeof(GDAL_GCP) );
    00955         psGCP->pszId = CPLStrdup("");
    00956         psGCP->pszInfo = CPLStrdup("");
    00957         psGCP++;
    00958     }
    00959 }
    00960
    00961 /************************************************************************/
    00962 /*                           GDALDeinitGCPs()                           */
    00963 /************************************************************************/
    00964
    00965 void GDALDeinitGCPs( int nCount, GDAL_GCP * psGCP )
    00966
    00967 {
    00968     for( int iGCP = 0; iGCP < nCount; iGCP++ )
    00969     {
    00970         CPLFree( psGCP->pszId );
    00971         CPLFree( psGCP->pszInfo );
    00972         psGCP++;
    00973     }
    00974 }
    00975
    00976 /************************************************************************/
    00977 /*                         GDALDuplicateGCPs()                          */
    00978 /************************************************************************/
    00979
    00980 GDAL_GCP *GDALDuplicateGCPs( int nCount, const GDAL_GCP *pasGCPList )
    00981
    00982 {
    00983     GDAL_GCP    *pasReturn;
    00984
    00985     pasReturn = (GDAL_GCP *) CPLMalloc(sizeof(GDAL_GCP) * nCount);
    00986     GDALInitGCPs( nCount, pasReturn );
    00987
    00988     for( int iGCP = 0; iGCP < nCount; iGCP++ )
    00989     {
    00990         CPLFree( pasReturn[iGCP].pszId );
    00991         pasReturn[iGCP].pszId = CPLStrdup( pasGCPList[iGCP].pszId );
    00992
    00993         CPLFree( pasReturn[iGCP].pszInfo );
    00994         pasReturn[iGCP].pszInfo = CPLStrdup( pasGCPList[iGCP].pszInfo );
    00995
    00996         pasReturn[iGCP].dfGCPPixel = pasGCPList[iGCP].dfGCPPixel;
    00997         pasReturn[iGCP].dfGCPLine = pasGCPList[iGCP].dfGCPLine;
    00998         pasReturn[iGCP].dfGCPX = pasGCPList[iGCP].dfGCPX;
    00999         pasReturn[iGCP].dfGCPY = pasGCPList[iGCP].dfGCPY;
    01000         pasReturn[iGCP].dfGCPZ = pasGCPList[iGCP].dfGCPZ;
    01001     }
    01002
    01003     return pasReturn;
    01004 }
    01005