00001 /****************************************************************************** 00002 * $Id: gdal_misc_cpp-source.html,v 1.10 2002/04/16 13:11:48 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.10 2002/04/16 13:11:48 warmerda 00030 * updated 00030 * 00031 * Revision 1.29 2001/12/07 20:04:21 warmerda 00032 * fixed serious bug in random sampler 00033 * 00034 * Revision 1.28 2001/11/30 03:41:26 warmerda 00035 * Fixed bug with the block sampling rate being too low to satisfy large 00036 * sample count values. Fixed bug with tiled images including some uninitialized 00037 * or zero data in the sample set on partial edge tiles. 00038 * 00039 * Revision 1.27 2001/11/26 20:14:01 warmerda 00040 * added GDALProjDef stubs for old 'bridges' 00041 * 00042 * Revision 1.26 2001/11/19 16:03:16 warmerda 00043 * moved GDALDectoDMS here 00044 * 00045 * Revision 1.25 2001/08/15 15:05:44 warmerda 00046 * return magnitude for complex samples in random sampler 00047 * 00048 * Revision 1.24 2001/07/18 04:04:30 warmerda 00049 * added CPL_CVSID 00050 * 00051 * Revision 1.23 2001/05/01 18:09:25 warmerda 00052 * added GDALReadWorldFile() 00053 * 00054 * Revision 1.22 2000/12/04 20:45:14 warmerda 00055 * removed unused variable. 00056 * 00057 * Revision 1.21 2000/10/06 15:22:49 warmerda 00058 * added GDALDataTypeUnion 00059 * 00060 * Revision 1.20 2000/08/18 15:24:48 warmerda 00061 * added GDALTermProgress 00062 * 00063 * Revision 1.19 2000/08/09 16:25:42 warmerda 00064 * don't crash if block is null 00065 * 00066 * Revision 1.18 2000/07/11 14:35:43 warmerda 00067 * added documentation 00068 * 00069 * Revision 1.17 2000/07/05 17:53:33 warmerda 00070 * Removed unused code related to nXCheck. 00071 * 00072 * Revision 1.16 2000/06/27 17:21:26 warmerda 00073 * added GDALGetRasterSampleOverview 00074 * 00075 * Revision 1.15 2000/06/26 22:17:49 warmerda 00076 * added scaled progress support 00077 * 00078 * Revision 1.14 2000/06/05 17:24:05 warmerda 00079 * added real complex support 00080 * 00081 * Revision 1.13 2000/04/21 21:55:32 warmerda 00082 * made more robust if block read fails 00083 * 00084 * Revision 1.12 2000/04/17 20:59:40 warmerda 00085 * Removed printf. 00086 * 00087 * Revision 1.11 2000/04/17 20:59:14 warmerda 00088 * fixed sampling bug 00089 * 00090 * Revision 1.10 2000/03/31 13:41:45 warmerda 00091 * added gcp support functions 00092 * 00093 * Revision 1.9 2000/03/24 00:09:19 warmerda 00094 * added sort-of random sampling 00095 * 00096 * Revision 1.8 2000/03/23 16:53:21 warmerda 00097 * use overviews for approximate min/max 00098 * 00099 * Revision 1.7 2000/03/09 23:21:44 warmerda 00100 * added GDALDummyProgress 00101 * 00102 * Revision 1.6 2000/03/06 21:59:44 warmerda 00103 * added min/max calculate 00104 * 00105 * Revision 1.5 2000/03/06 02:20:15 warmerda 00106 * added getname functions for colour interpretations 00107 * 00108 * Revision 1.4 1999/07/23 19:35:47 warmerda 00109 * added GDALGetDataTypeName 00110 * 00111 * Revision 1.3 1999/05/17 02:00:45 vgough 00112 * made pure_virtual C linkage 00113 * 00114 * Revision 1.2 1999/05/16 19:32:13 warmerda 00115 * Added __pure_virtual. 00116 * 00117 * Revision 1.1 1998/12/06 02:50:16 warmerda 00118 * New 00119 * 00120 */ 00121 00122 #include "gdal_priv.h" 00123 #include "cpl_string.h" 00124 00125 CPL_CVSID("$Id: gdal_misc_cpp-source.html,v 1.10 2002/04/16 13:11:48 warmerda Exp $"); 00126 00127 /************************************************************************/ 00128 /* __pure_virtual() */ 00129 /* */ 00130 /* The following is a gross hack to remove the last remaining */ 00131 /* dependency on the GNU C++ standard library. */ 00132 /************************************************************************/ 00133 00134 #ifdef __GNUC__ 00135 00136 extern "C" 00137 void __pure_virtual() 00138 00139 { 00140 } 00141 00142 #endif 00143 00144 /************************************************************************/ 00145 /* GDALDataTypeUnion() */ 00146 /************************************************************************/ 00147 00158 GDALDataType GDALDataTypeUnion( GDALDataType eType1, GDALDataType eType2 ) 00159 00160 { 00161 int bFloating, bComplex, nBits, bSigned; 00162 00163 bComplex = GDALDataTypeIsComplex(eType1) | GDALDataTypeIsComplex(eType2); 00164 00165 switch( eType1 ) 00166 { 00167 case GDT_Byte: 00168 nBits = 8; 00169 bSigned = FALSE; 00170 bFloating = FALSE; 00171 break; 00172 00173 case GDT_Int16: 00174 case GDT_CInt16: 00175 nBits = 16; 00176 bSigned = TRUE; 00177 bFloating = FALSE; 00178 break; 00179 00180 case GDT_UInt16: 00181 nBits = 16; 00182 bSigned = FALSE; 00183 bFloating = FALSE; 00184 break; 00185 00186 case GDT_Int32: 00187 case GDT_CInt32: 00188 nBits = 32; 00189 bSigned = TRUE; 00190 bFloating = FALSE; 00191 break; 00192 00193 case GDT_UInt32: 00194 nBits = 32; 00195 bSigned = FALSE; 00196 bFloating = FALSE; 00197 break; 00198 00199 case GDT_Float32: 00200 case GDT_CFloat32: 00201 nBits = 32; 00202 bSigned = TRUE; 00203 bFloating = TRUE; 00204 break; 00205 00206 case GDT_Float64: 00207 case GDT_CFloat64: 00208 nBits = 64; 00209 bSigned = TRUE; 00210 bFloating = TRUE; 00211 break; 00212 00213 default: 00214 CPLAssert( FALSE ); 00215 return GDT_Unknown; 00216 } 00217 00218 switch( eType2 ) 00219 { 00220 case GDT_Byte: 00221 break; 00222 00223 case GDT_Int16: 00224 nBits = MAX(nBits,16); 00225 bSigned = TRUE; 00226 break; 00227 00228 case GDT_UInt16: 00229 nBits = MAX(nBits,16); 00230 break; 00231 00232 case GDT_Int32: 00233 case GDT_CInt32: 00234 nBits = MAX(nBits,32); 00235 bSigned = TRUE; 00236 break; 00237 00238 case GDT_UInt32: 00239 nBits = MAX(nBits,32); 00240 break; 00241 00242 case GDT_Float32: 00243 case GDT_CFloat32: 00244 nBits = MAX(nBits,32); 00245 bSigned = TRUE; 00246 bFloating = TRUE; 00247 break; 00248 00249 case GDT_Float64: 00250 case GDT_CFloat64: 00251 nBits = MAX(nBits,64); 00252 bSigned = TRUE; 00253 bFloating = TRUE; 00254 break; 00255 00256 default: 00257 CPLAssert( FALSE ); 00258 return GDT_Unknown; 00259 } 00260 00261 if( nBits == 8 ) 00262 return GDT_Byte; 00263 else if( nBits == 16 && bComplex ) 00264 return GDT_CInt16; 00265 else if( nBits == 16 && bSigned ) 00266 return GDT_Int16; 00267 else if( nBits == 16 && !bSigned ) 00268 return GDT_UInt16; 00269 else if( nBits == 32 && bFloating && bComplex ) 00270 return GDT_CFloat32; 00271 else if( nBits == 32 && bFloating ) 00272 return GDT_Float32; 00273 else if( nBits == 32 && bComplex ) 00274 return GDT_CInt32; 00275 else if( nBits == 32 && bSigned ) 00276 return GDT_Int32; 00277 else if( nBits == 32 && !bSigned ) 00278 return GDT_UInt32; 00279 else if( nBits == 64 && bComplex ) 00280 return GDT_CFloat64; 00281 else 00282 return GDT_Float64; 00283 } 00284 00285 00286 /************************************************************************/ 00287 /* GDALGetDataTypeSize() */ 00288 /************************************************************************/ 00289 int GDALGetDataTypeSize( GDALDataType eDataType ) 00290 00291 { 00292 switch( eDataType ) 00293 { 00294 case GDT_Byte: 00295 return 8; 00296 00297 case GDT_UInt16: 00298 case GDT_Int16: 00299 return 16; 00300 00301 case GDT_UInt32: 00302 case GDT_Int32: 00303 case GDT_Float32: 00304 case GDT_CInt16: 00305 return 32; 00306 00307 case GDT_Float64: 00308 case GDT_CInt32: 00309 case GDT_CFloat32: 00310 return 64; 00311 00312 case GDT_CFloat64: 00313 return 128; 00314 00315 default: 00316 CPLAssert( FALSE ); 00317 return 0; 00318 } 00319 } 00320 00321 /************************************************************************/ 00322 /* GDALDataTypeIsComplex() */ 00323 /************************************************************************/ 00324 00325 int GDALDataTypeIsComplex( GDALDataType eDataType ) 00326 00327 { 00328 switch( eDataType ) 00329 { 00330 case GDT_CInt16: 00331 case GDT_CInt32: 00332 case GDT_CFloat32: 00333 case GDT_CFloat64: 00334 return TRUE; 00335 00336 default: 00337 return FALSE; 00338 } 00339 } 00340 00341 /************************************************************************/ 00342 /* GDALGetDataTypeName() */ 00343 /************************************************************************/ 00344 00345 const char *GDALGetDataTypeName( GDALDataType eDataType ) 00346 00347 { 00348 switch( eDataType ) 00349 { 00350 case GDT_Byte: 00351 return "Byte"; 00352 00353 case GDT_UInt16: 00354 return "UInt16"; 00355 00356 case GDT_Int16: 00357 return "Int16"; 00358 00359 case GDT_UInt32: 00360 return "UInt32"; 00361 00362 case GDT_Int32: 00363 return "Int32"; 00364 00365 case GDT_Float32: 00366 return "Float32"; 00367 00368 case GDT_Float64: 00369 return "Float64"; 00370 00371 case GDT_CInt16: 00372 return "CInt16"; 00373 00374 case GDT_CInt32: 00375 return "CInt32"; 00376 00377 case GDT_CFloat32: 00378 return "CFloat32"; 00379 00380 case GDT_CFloat64: 00381 return "CFloat64"; 00382 00383 default: 00384 return NULL; 00385 } 00386 } 00387 00388 /************************************************************************/ 00389 /* GDALGetPaletteInterpretationName() */ 00390 /************************************************************************/ 00391 00392 const char *GDALGetPaletteInterpretationName( GDALPaletteInterp eInterp ) 00393 00394 { 00395 switch( eInterp ) 00396 { 00397 case GPI_Gray: 00398 return "Gray"; 00399 00400 case GPI_RGB: 00401 return "RGB"; 00402 00403 case GPI_CMYK: 00404 return "CMYK"; 00405 00406 case GPI_HLS: 00407 return "HLS"; 00408 00409 default: 00410 return "Unknown"; 00411 } 00412 } 00413 00414 /************************************************************************/ 00415 /* GDALGetColorInterpretationName() */ 00416 /************************************************************************/ 00417 00418 const char *GDALGetColorInterpretationName( GDALColorInterp eInterp ) 00419 00420 { 00421 switch( eInterp ) 00422 { 00423 case GCI_Undefined: 00424 return "Undefined"; 00425 00426 case GCI_GrayIndex: 00427 return "Gray"; 00428 00429 case GCI_PaletteIndex: 00430 return "Palette"; 00431 00432 case GCI_RedBand: 00433 return "Red"; 00434 00435 case GCI_GreenBand: 00436 return "Green"; 00437 00438 case GCI_BlueBand: 00439 return "Blue"; 00440 00441 case GCI_AlphaBand: 00442 return "Alpha"; 00443 00444 case GCI_HueBand: 00445 return "Hue"; 00446 00447 case GCI_SaturationBand: 00448 return "Saturation"; 00449 00450 case GCI_LightnessBand: 00451 return "Lightness"; 00452 00453 case GCI_CyanBand: 00454 return "Cyan"; 00455 00456 case GCI_MagentaBand: 00457 return "Magenta"; 00458 00459 case GCI_YellowBand: 00460 return "Yellow"; 00461 00462 case GCI_BlackBand: 00463 return "Black"; 00464 00465 default: 00466 return "Unknown"; 00467 } 00468 } 00469 00470 /************************************************************************/ 00471 /* GDALComputeRasterMinMax() */ 00472 /************************************************************************/ 00473 00492 void GDALComputeRasterMinMax( GDALRasterBandH hBand, int bApproxOK, 00493 double adfMinMax[2] ) 00494 00495 { 00496 double dfMin=0.0, dfMax=0.0; 00497 GDALRasterBand *poBand; 00498 00499 /* -------------------------------------------------------------------- */ 00500 /* Does the driver already know the min/max? */ 00501 /* -------------------------------------------------------------------- */ 00502 if( bApproxOK ) 00503 { 00504 int bSuccessMin, bSuccessMax; 00505 00506 dfMin = GDALGetRasterMinimum( hBand, &bSuccessMin ); 00507 dfMax = GDALGetRasterMaximum( hBand, &bSuccessMax ); 00508 00509 if( bSuccessMin && bSuccessMax ) 00510 { 00511 adfMinMax[0] = dfMin; 00512 adfMinMax[1] = dfMax; 00513 return; 00514 } 00515 } 00516 00517 /* -------------------------------------------------------------------- */ 00518 /* If we have overview bands, use them for min/max. */ 00519 /* -------------------------------------------------------------------- */ 00520 if( bApproxOK ) 00521 poBand = (GDALRasterBand *) GDALGetRasterSampleOverview( hBand, 2500 ); 00522 else 00523 poBand = (GDALRasterBand *) hBand; 00524 00525 /* -------------------------------------------------------------------- */ 00526 /* Figure out the ratio of blocks we will read to get an */ 00527 /* approximate value. */ 00528 /* -------------------------------------------------------------------- */ 00529 int nBlockXSize, nBlockYSize; 00530 int nBlocksPerRow, nBlocksPerColumn; 00531 int nSampleRate; 00532 int bGotNoDataValue, bFirstValue = TRUE; 00533 double dfNoDataValue; 00534 00535 dfNoDataValue = poBand->GetNoDataValue( &bGotNoDataValue ); 00536 00537 poBand->GetBlockSize( &nBlockXSize, &nBlockYSize ); 00538 nBlocksPerRow = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize; 00539 nBlocksPerColumn = (poBand->GetYSize() + nBlockYSize - 1) / nBlockYSize; 00540 00541 if( bApproxOK ) 00542 nSampleRate = 00543 (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn)); 00544 else 00545 nSampleRate = 1; 00546 00547 for( int iSampleBlock = 0; 00548 iSampleBlock < nBlocksPerRow * nBlocksPerColumn; 00549 iSampleBlock += nSampleRate ) 00550 { 00551 double dfValue = 0.0; 00552 int iXBlock, iYBlock, nXCheck, nYCheck; 00553 GDALRasterBlock *poBlock; 00554 00555 iYBlock = iSampleBlock / nBlocksPerRow; 00556 iXBlock = iSampleBlock - nBlocksPerRow * iYBlock; 00557 00558 poBlock = poBand->GetBlockRef( iXBlock, iYBlock ); 00559 if( poBlock == NULL ) 00560 continue; 00561 00562 if( (iXBlock+1) * nBlockXSize > poBand->GetXSize() ) 00563 nXCheck = poBand->GetXSize() - iXBlock * nBlockXSize; 00564 else 00565 nXCheck = nBlockXSize; 00566 00567 if( (iYBlock+1) * nBlockYSize > poBand->GetYSize() ) 00568 nYCheck = poBand->GetYSize() - iYBlock * nBlockYSize; 00569 else 00570 nYCheck = nBlockYSize; 00571 00572 /* this isn't the fastest way to do this, but is easier for now */ 00573 for( int iY = 0; iY < nYCheck; iY++ ) 00574 { 00575 for( int iX = 0; iX < nXCheck; iX++ ) 00576 { 00577 int iOffset = iX + iY * nBlockXSize; 00578 00579 switch( poBlock->GetDataType() ) 00580 { 00581 case GDT_Byte: 00582 dfValue = ((GByte *) poBlock->GetDataRef())[iOffset]; 00583 break; 00584 case GDT_UInt16: 00585 dfValue = ((GUInt16 *) poBlock->GetDataRef())[iOffset]; 00586 break; 00587 case GDT_Int16: 00588 dfValue = ((GInt16 *) poBlock->GetDataRef())[iOffset]; 00589 break; 00590 case GDT_UInt32: 00591 dfValue = ((GUInt32 *) poBlock->GetDataRef())[iOffset]; 00592 break; 00593 case GDT_Int32: 00594 dfValue = ((GInt32 *) poBlock->GetDataRef())[iOffset]; 00595 break; 00596 case GDT_Float32: 00597 dfValue = ((float *) poBlock->GetDataRef())[iOffset]; 00598 break; 00599 case GDT_Float64: 00600 dfValue = ((double *) poBlock->GetDataRef())[iOffset]; 00601 break; 00602 case GDT_CInt16: 00603 dfValue = ((GInt16 *) poBlock->GetDataRef())[iOffset*2]; 00604 break; 00605 case GDT_CInt32: 00606 dfValue = ((GInt32 *) poBlock->GetDataRef())[iOffset*2]; 00607 break; 00608 case GDT_CFloat32: 00609 dfValue = ((float *) poBlock->GetDataRef())[iOffset*2]; 00610 break; 00611 case GDT_CFloat64: 00612 dfValue = ((double *) poBlock->GetDataRef())[iOffset*2]; 00613 break; 00614 default: 00615 CPLAssert( FALSE ); 00616 } 00617 00618 if( bGotNoDataValue && dfValue == dfNoDataValue ) 00619 continue; 00620 00621 if( bFirstValue ) 00622 { 00623 dfMin = dfMax = dfValue; 00624 bFirstValue = FALSE; 00625 } 00626 else 00627 { 00628 dfMin = MIN(dfMin,dfValue); 00629 dfMax = MAX(dfMax,dfValue); 00630 } 00631 } 00632 } 00633 } 00634 00635 adfMinMax[0] = dfMin; 00636 adfMinMax[1] = dfMax; 00637 } 00638 00639 /************************************************************************/ 00640 /* GDALDummyProgress() */ 00641 /************************************************************************/ 00642 00707 int GDALDummyProgress( double, const char *, void * ) 00708 00709 { 00710 return TRUE; 00711 } 00712 00713 /************************************************************************/ 00714 /* GDALScaledProgress() */ 00715 /************************************************************************/ 00716 typedef struct { 00717 GDALProgressFunc pfnProgress; 00718 void *pData; 00719 double dfMin; 00720 double dfMax; 00721 } GDALScaledProgressInfo; 00722 00723 int GDALScaledProgress( double dfComplete, const char *pszMessage, 00724 void *pData ) 00725 00726 { 00727 GDALScaledProgressInfo *psInfo = (GDALScaledProgressInfo *) pData; 00728 00729 return psInfo->pfnProgress( dfComplete * (psInfo->dfMax - psInfo->dfMin) 00730 + psInfo->dfMin, 00731 pszMessage, psInfo->pData ); 00732 } 00733 00734 /************************************************************************/ 00735 /* GDALCreateScaledProgress() */ 00736 /************************************************************************/ 00737 00738 void *GDALCreateScaledProgress( double dfMin, double dfMax, 00739 GDALProgressFunc pfnProgress, 00740 void * pData ) 00741 00742 { 00743 GDALScaledProgressInfo *psInfo; 00744 00745 psInfo = (GDALScaledProgressInfo *) 00746 CPLCalloc(sizeof(GDALScaledProgressInfo),1); 00747 00748 if( ABS(dfMin-dfMax) < 0.0000001 ) 00749 dfMax = dfMin + 0.01; 00750 00751 psInfo->pData = pData; 00752 psInfo->pfnProgress = pfnProgress; 00753 psInfo->dfMin = dfMin; 00754 psInfo->dfMax = dfMax; 00755 00756 return (void *) psInfo; 00757 } 00758 00759 /************************************************************************/ 00760 /* GDALDestroyScaledProgress() */ 00761 /************************************************************************/ 00762 00763 void GDALDestroyScaledProgress( void * pData ) 00764 00765 { 00766 CPLFree( pData ); 00767 } 00768 00769 /************************************************************************/ 00770 /* GDALTermProgress() */ 00771 /************************************************************************/ 00772 00773 int GDALTermProgress( double dfComplete, const char *pszMessage, void * ) 00774 00775 { 00776 static double dfLastComplete = -1.0; 00777 00778 if( dfLastComplete > dfComplete ) 00779 { 00780 if( dfLastComplete > 1.0 ) 00781 dfLastComplete = -1.0; 00782 else 00783 dfLastComplete = dfComplete; 00784 } 00785 00786 if( floor(dfLastComplete*10) != floor(dfComplete*10) ) 00787 { 00788 int nPercent = (int) floor(dfComplete*100); 00789 00790 if( nPercent == 0 && pszMessage != NULL ) 00791 fprintf( stdout, "%s:", pszMessage ); 00792 00793 if( nPercent == 100 ) 00794 fprintf( stdout, "%d - done.\n", (int) floor(dfComplete*100) ); 00795 else 00796 { 00797 fprintf( stdout, "%d.", (int) floor(dfComplete*100) ); 00798 fflush( stdout ); 00799 } 00800 } 00801 else if( floor(dfLastComplete*30) != floor(dfComplete*30) ) 00802 { 00803 fprintf( stdout, "." ); 00804 fflush( stdout ); 00805 } 00806 00807 dfLastComplete = dfComplete; 00808 00809 return TRUE; 00810 } 00811 00812 /************************************************************************/ 00813 /* GDALGetRasterSampleOverview() */ 00814 /************************************************************************/ 00815 00831 GDALRasterBandH GDALGetRasterSampleOverview( GDALRasterBandH hBand, 00832 int nDesiredSamples ) 00833 00834 { 00835 int nBestSamples; 00836 GDALRasterBandH hBestBand = hBand; 00837 00838 nBestSamples = GDALGetRasterBandXSize(hBand) 00839 * GDALGetRasterBandYSize(hBand); 00840 00841 for( int iOverview = 0; 00842 iOverview < GDALGetOverviewCount( hBand ); 00843 iOverview++ ) 00844 { 00845 GDALRasterBandH hOBand = GDALGetOverview( hBand, iOverview ); 00846 int nOSamples; 00847 00848 nOSamples = GDALGetRasterBandXSize(hOBand) 00849 * GDALGetRasterBandYSize(hOBand); 00850 00851 if( nOSamples < nBestSamples && nOSamples > nDesiredSamples ) 00852 { 00853 nBestSamples = nOSamples; 00854 hBestBand = hOBand; 00855 } 00856 } 00857 00858 return hBestBand; 00859 } 00860 00861 /************************************************************************/ 00862 /* GDALGetRandomRasterSample() */ 00863 /************************************************************************/ 00864 00865 int GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples, 00866 float *pafSampleBuf ) 00867 00868 { 00869 GDALRasterBand *poBand; 00870 00871 poBand = (GDALRasterBand *) GDALGetRasterSampleOverview( hBand, nSamples ); 00872 00873 /* -------------------------------------------------------------------- */ 00874 /* Figure out the ratio of blocks we will read to get an */ 00875 /* approximate value. */ 00876 /* -------------------------------------------------------------------- */ 00877 int nBlockXSize, nBlockYSize; 00878 int nBlocksPerRow, nBlocksPerColumn; 00879 int nSampleRate; 00880 int bGotNoDataValue; 00881 double dfNoDataValue; 00882 int nActualSamples = 0; 00883 int nBlockSampleRate; 00884 int nBlockPixels, nBlockCount; 00885 00886 dfNoDataValue = poBand->GetNoDataValue( &bGotNoDataValue ); 00887 00888 poBand->GetBlockSize( &nBlockXSize, &nBlockYSize ); 00889 00890 nBlocksPerRow = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize; 00891 nBlocksPerColumn = (poBand->GetYSize() + nBlockYSize - 1) / nBlockYSize; 00892 00893 nBlockPixels = nBlockXSize * nBlockYSize; 00894 nBlockCount = nBlocksPerRow * nBlocksPerColumn; 00895 00896 nSampleRate = (int) MAX(1,sqrt((double) nBlockCount)-2.0); 00897 00898 if( nSampleRate == nBlocksPerRow && nSampleRate > 1 ) 00899 nSampleRate--; 00900 00901 while( nSampleRate > 1 00902 && ((nBlockCount-1) / nSampleRate + 1) * nBlockPixels < nSamples ) 00903 nSampleRate--; 00904 00905 nBlockSampleRate = 00906 MAX(1,nBlockPixels / (nSamples / ((nBlockCount-1) / nSampleRate + 1))); 00907 00908 for( int iSampleBlock = 0; 00909 iSampleBlock < nBlockCount; 00910 iSampleBlock += nSampleRate ) 00911 { 00912 double dfValue = 0.0, dfReal, dfImag; 00913 int iXBlock, iYBlock, iX, iY, iXValid, iYValid, iRemainder = 0; 00914 GDALRasterBlock *poBlock; 00915 00916 iYBlock = iSampleBlock / nBlocksPerRow; 00917 iXBlock = iSampleBlock - nBlocksPerRow * iYBlock; 00918 00919 poBlock = poBand->GetBlockRef( iXBlock, iYBlock ); 00920 if( poBlock == NULL ) 00921 continue; 00922 00923 if( iXBlock * nBlockXSize > poBand->GetXSize() ) 00924 iXValid = poBand->GetXSize() - iXBlock * nBlockXSize; 00925 else 00926 iXValid = nBlockXSize; 00927 00928 if( iYBlock * nBlockYSize > poBand->GetYSize() ) 00929 iYValid = poBand->GetYSize() - iYBlock * nBlockYSize; 00930 else 00931 iYValid = nBlockYSize; 00932 00933 for( iY = 0; iY < iYValid; iY++ ) 00934 { 00935 for( iX = iRemainder; iX < iXValid; iX += nBlockSampleRate ) 00936 { 00937 int iOffset; 00938 00939 iOffset = iX + iY * nBlockXSize; 00940 switch( poBlock->GetDataType() ) 00941 { 00942 case GDT_Byte: 00943 dfValue = ((GByte *) poBlock->GetDataRef())[iOffset]; 00944 break; 00945 case GDT_UInt16: 00946 dfValue = ((GUInt16 *) poBlock->GetDataRef())[iOffset]; 00947 break; 00948 case GDT_Int16: 00949 dfValue = ((GInt16 *) poBlock->GetDataRef())[iOffset]; 00950 break; 00951 case GDT_UInt32: 00952 dfValue = ((GUInt32 *) poBlock->GetDataRef())[iOffset]; 00953 break; 00954 case GDT_Int32: 00955 dfValue = ((GInt32 *) poBlock->GetDataRef())[iOffset]; 00956 break; 00957 case GDT_Float32: 00958 dfValue = ((float *) poBlock->GetDataRef())[iOffset]; 00959 break; 00960 case GDT_Float64: 00961 dfValue = ((double *) poBlock->GetDataRef())[iOffset]; 00962 break; 00963 case GDT_CInt16: 00964 dfReal = ((GInt16 *) poBlock->GetDataRef())[iOffset*2]; 00965 dfImag = ((GInt16 *) poBlock->GetDataRef())[iOffset*2+1]; 00966 dfValue = sqrt(dfReal*dfReal + dfImag*dfImag); 00967 break; 00968 case GDT_CInt32: 00969 dfReal = ((GInt32 *) poBlock->GetDataRef())[iOffset*2]; 00970 dfImag = ((GInt32 *) poBlock->GetDataRef())[iOffset*2+1]; 00971 dfValue = sqrt(dfReal*dfReal + dfImag*dfImag); 00972 break; 00973 case GDT_CFloat32: 00974 dfReal = ((float *) poBlock->GetDataRef())[iOffset*2]; 00975 dfImag = ((float *) poBlock->GetDataRef())[iOffset*2+1]; 00976 dfValue = sqrt(dfReal*dfReal + dfImag*dfImag); 00977 break; 00978 case GDT_CFloat64: 00979 dfReal = ((double *) poBlock->GetDataRef())[iOffset*2]; 00980 dfImag = ((double *) poBlock->GetDataRef())[iOffset*2+1]; 00981 dfValue = sqrt(dfReal*dfReal + dfImag*dfImag); 00982 break; 00983 default: 00984 CPLAssert( FALSE ); 00985 } 00986 00987 if( bGotNoDataValue && dfValue == dfNoDataValue ) 00988 continue; 00989 00990 if( nActualSamples < nSamples ) 00991 pafSampleBuf[nActualSamples++] = dfValue; 00992 } 00993 00994 iRemainder = iX - iXValid; 00995 } 00996 } 00997 00998 return nActualSamples; 00999 } 01000 01001 /************************************************************************/ 01002 /* GDALInitGCPs() */ 01003 /************************************************************************/ 01004 01005 void GDALInitGCPs( int nCount, GDAL_GCP * psGCP ) 01006 01007 { 01008 for( int iGCP = 0; iGCP < nCount; iGCP++ ) 01009 { 01010 memset( psGCP, 0, sizeof(GDAL_GCP) ); 01011 psGCP->pszId = CPLStrdup(""); 01012 psGCP->pszInfo = CPLStrdup(""); 01013 psGCP++; 01014 } 01015 } 01016 01017 /************************************************************************/ 01018 /* GDALDeinitGCPs() */ 01019 /************************************************************************/ 01020 01021 void GDALDeinitGCPs( int nCount, GDAL_GCP * psGCP ) 01022 01023 { 01024 for( int iGCP = 0; iGCP < nCount; iGCP++ ) 01025 { 01026 CPLFree( psGCP->pszId ); 01027 CPLFree( psGCP->pszInfo ); 01028 psGCP++; 01029 } 01030 } 01031 01032 /************************************************************************/ 01033 /* GDALDuplicateGCPs() */ 01034 /************************************************************************/ 01035 01036 GDAL_GCP *GDALDuplicateGCPs( int nCount, const GDAL_GCP *pasGCPList ) 01037 01038 { 01039 GDAL_GCP *pasReturn; 01040 01041 pasReturn = (GDAL_GCP *) CPLMalloc(sizeof(GDAL_GCP) * nCount); 01042 GDALInitGCPs( nCount, pasReturn ); 01043 01044 for( int iGCP = 0; iGCP < nCount; iGCP++ ) 01045 { 01046 CPLFree( pasReturn[iGCP].pszId ); 01047 pasReturn[iGCP].pszId = CPLStrdup( pasGCPList[iGCP].pszId ); 01048 01049 CPLFree( pasReturn[iGCP].pszInfo ); 01050 pasReturn[iGCP].pszInfo = CPLStrdup( pasGCPList[iGCP].pszInfo ); 01051 01052 pasReturn[iGCP].dfGCPPixel = pasGCPList[iGCP].dfGCPPixel; 01053 pasReturn[iGCP].dfGCPLine = pasGCPList[iGCP].dfGCPLine; 01054 pasReturn[iGCP].dfGCPX = pasGCPList[iGCP].dfGCPX; 01055 pasReturn[iGCP].dfGCPY = pasGCPList[iGCP].dfGCPY; 01056 pasReturn[iGCP].dfGCPZ = pasGCPList[iGCP].dfGCPZ; 01057 } 01058 01059 return pasReturn; 01060 } 01061 01062 /************************************************************************/ 01063 /* GDALReadWorldFile() */ 01064 /* */ 01065 /* Helper function for translator implementators wanting */ 01066 /* support for ESRI world files. */ 01067 /************************************************************************/ 01068 01069 int GDALReadWorldFile( const char * pszBaseFilename, const char *pszExtension, 01070 double *padfGeoTransform ) 01071 01072 { 01073 const char *pszTFW; 01074 char szExtUpper[32], szExtLower[32]; 01075 int i; 01076 FILE *fpTFW; 01077 char **papszLines; 01078 01079 if( *pszExtension == '.' ) 01080 pszExtension++; 01081 01082 /* -------------------------------------------------------------------- */ 01083 /* Generate upper and lower case versions of the extension. */ 01084 /* -------------------------------------------------------------------- */ 01085 strcpy( szExtUpper, pszExtension ); 01086 strcpy( szExtLower, pszExtension ); 01087 01088 for( i = 0; szExtUpper[i] != '\0'; i++ ) 01089 { 01090 if( szExtUpper[i] >= 'a' && szExtUpper[i] <= 'z' ) 01091 szExtUpper[i] = szExtUpper[i] - 'a' + 'A'; 01092 if( szExtLower[i] >= 'A' && szExtLower[i] <= 'Z' ) 01093 szExtLower[i] = szExtLower[i] - 'A' + 'a'; 01094 } 01095 01096 /* -------------------------------------------------------------------- */ 01097 /* Try lower case, then upper case. */ 01098 /* -------------------------------------------------------------------- */ 01099 pszTFW = CPLResetExtension( pszBaseFilename, szExtLower ); 01100 01101 fpTFW = VSIFOpen( pszTFW, "rt" ); 01102 01103 #ifndef WIN32 01104 if( fpTFW == NULL ) 01105 { 01106 pszTFW = CPLResetExtension( pszBaseFilename, szExtUpper ); 01107 fpTFW = VSIFOpen( pszTFW, "rt" ); 01108 } 01109 #endif 01110 01111 if( fpTFW == NULL ) 01112 return FALSE; 01113 01114 VSIFClose( fpTFW ); 01115 01116 /* -------------------------------------------------------------------- */ 01117 /* We found the file, now load and parse it. */ 01118 /* -------------------------------------------------------------------- */ 01119 papszLines = CSLLoad( pszTFW ); 01120 if( CSLCount(papszLines) >= 6 01121 && atof(papszLines[0]) != 0.0 01122 && atof(papszLines[3]) != 0.0 ) 01123 { 01124 padfGeoTransform[0] = atof(papszLines[4]); 01125 padfGeoTransform[1] = atof(papszLines[0]); 01126 padfGeoTransform[2] = atof(papszLines[2]); 01127 padfGeoTransform[3] = atof(papszLines[5]); 01128 padfGeoTransform[4] = atof(papszLines[1]); 01129 padfGeoTransform[5] = atof(papszLines[3]); 01130 01131 // correct for center of pixel vs. top left of pixel 01132 padfGeoTransform[0] -= 0.5 * padfGeoTransform[1]; 01133 padfGeoTransform[0] -= 0.5 * padfGeoTransform[2]; 01134 padfGeoTransform[3] -= 0.5 * padfGeoTransform[4]; 01135 padfGeoTransform[3] -= 0.5 * padfGeoTransform[5]; 01136 01137 CSLDestroy(papszLines); 01138 01139 return TRUE; 01140 } 01141 else 01142 { 01143 CPLDebug( "GDAL", 01144 "GDALReadWorldFile(%s) found file, but it was corrupt.", 01145 pszTFW ); 01146 CSLDestroy(papszLines); 01147 return FALSE; 01148 } 01149 } 01150 01151 /************************************************************************/ 01152 /* GDALDecToDMS() */ 01153 /* */ 01154 /* Translate a decimal degrees value to a DMS string with */ 01155 /* hemisphere. */ 01156 /************************************************************************/ 01157 01158 const char *GDALDecToDMS( double dfAngle, const char * pszAxis, 01159 int nPrecision ) 01160 01161 { 01162 int nDegrees, nMinutes; 01163 double dfSeconds; 01164 char szFormat[30]; 01165 static char szBuffer[50]; 01166 const char *pszHemisphere; 01167 01168 01169 nDegrees = (int) ABS(dfAngle); 01170 nMinutes = (int) ((ABS(dfAngle) - nDegrees) * 60); 01171 dfSeconds = (ABS(dfAngle) * 3600 - nDegrees*3600 - nMinutes*60); 01172 01173 if( EQUAL(pszAxis,"Long") && dfAngle < 0.0 ) 01174 pszHemisphere = "W"; 01175 else if( EQUAL(pszAxis,"Long") ) 01176 pszHemisphere = "E"; 01177 else if( dfAngle < 0.0 ) 01178 pszHemisphere = "S"; 01179 else 01180 pszHemisphere = "N"; 01181 01182 sprintf( szFormat, "%%3dd%%2d\'%%.%df\"%s", nPrecision, pszHemisphere ); 01183 sprintf( szBuffer, szFormat, nDegrees, nMinutes, dfSeconds ); 01184 01185 return( szBuffer ); 01186 } 01187 01188 /************************************************************************/ 01189 /* -------------------------------------------------------------------- */ 01190 /* The following stubs are present to ensure that older GDAL */ 01191 /* bridges don't fail with newer libraries. */ 01192 /* -------------------------------------------------------------------- */ 01193 /************************************************************************/ 01194 01195 CPL_C_START 01196 01197 void *GDALCreateProjDef( const char * pszDef ) 01198 { 01199 CPLDebug( "GDAL", "GDALCreateProjDef no longer supported." ); 01200 return NULL; 01201 } 01202 01203 CPLErr GDALReprojectToLongLat( void *pDef, double *, double * ) 01204 { 01205 CPLDebug( "GDAL", "GDALReprojectToLatLong no longer supported." ); 01206 return CE_Failure; 01207 } 01208 01209 CPLErr GDALReprojectFromLongLat( void *pDef, double *, double * ) 01210 { 01211 CPLDebug( "GDAL", "GDALReprojectFromLatLong no longer supported." ); 01212 return CE_Failure; 01213 } 01214 01215 void GDALDestroyProjDef( void *pDef ) 01216 01217 { 01218 CPLDebug( "GDAL", "GDALDestroyProjDef no longer supported." ); 01219 } 01220 01221 CPL_C_END