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.5 2000/11/06 04:49:01 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.5  2000/11/06 04:49:01  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                              

doxygen1.2.3-20001105 Dimitri van Heesch, © 1997-2000