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