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