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