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