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

gdal_misc.cpp

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

Generated at Thu Jul 5 09:16:12 2001 for GDAL by doxygen1.2.3-20001105 written by Dimitri van Heesch, © 1997-2000