00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023 00024 00025 00026 00027 00028 00029 00030 00030 00030 00030 00031 00032 00033 00034 00035 00036 00037 00038 00039 00040 00041 00042 00043 00044 00045 00046 00047 00048 00049 00050 00051 00052 00053 00054 00055 00056 00057 00058 00059 00060 00061 00062 00063 00064 00065 00066 00067 00068 00069 00070 00071 00072 00073 00074 00075 00076 00077 00078 00079 00080 00081 00082 00083 00084 00085 00086 00087 00088 00089 00090 00091 00092 00093
00094
00095 #include "gdal_priv.h"
00096 #include "cpl_string.h"
00097
00098
00099
00100
00101
00104 GDALRasterBand::GDALRasterBand()
00105
00106 {
00107 poDS = NULL;
00108 nBand = 0;
00109
00110 eAccess = GA_ReadOnly;
00111 nBlockXSize = nBlockYSize = -1;
00112 eDataType = GDT_Byte;
00113
00114 nBlocksPerRow = 0;
00115 nBlocksPerColumn = 0;
00116
00117 papoBlocks = NULL;
00118 }
00119
00120
00121
00122
00123
00127 GDALRasterBand::~GDALRasterBand()
00128
00129 {
00130 FlushCache();
00131
00132 CPLFree( papoBlocks );
00133 }
00134
00135
00136
00137
00138
00204 CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
00205 int nXOff, int nYOff, int nXSize, int nYSize,
00206 void * pData, int nBufXSize, int nBufYSize,
00207 GDALDataType eBufType,
00208 int nPixelSpace,
00209 int nLineSpace )
00210
00211 {
00212
00213
00214
00215
00216 if( nPixelSpace == 0 )
00217 nPixelSpace = GDALGetDataTypeSize( eBufType ) / 8;
00218
00219 if( nLineSpace == 0 )
00220 nLineSpace = nPixelSpace * nBufXSize;
00221
00222
00223
00224
00225 if( nXOff < 0 || nXOff + nXSize > nRasterXSize
00226 || nYOff < 0 || nYOff + nYSize > nRasterYSize )
00227 {
00228 CPLError( CE_Failure, CPLE_IllegalArg,
00229 "Access window out of range in RasterIO(). Requested\n"
00230 "(%d,%d) of size %dx%d on raster of %dx%d.",
00231 nXOff, nYOff, nXSize, nYSize, nRasterXSize, nRasterYSize );
00232 return CE_Failure;
00233 }
00234
00235
00236
00237
00238
00239 if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
00240 {
00241 CPLDebug( "GDAL",
00242 "RasterIO() skipped for odd window or buffer size.\n"
00243 " Window = (%d,%d)x%dx%d\n"
00244 " Buffer = %dx%d\n",
00245 nXOff, nYOff, nXSize, nYSize,
00246 nBufXSize, nBufYSize );
00247
00248 return CE_None;
00249 }
00250
00251
00252
00253
00254 return( IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
00255 pData, nBufXSize, nBufYSize, eBufType,
00256 nPixelSpace, nLineSpace ) );
00257 }
00258
00259
00260
00261
00262
00263 CPLErr GDALRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
00264 int nXOff, int nYOff,
00265 int nXSize, int nYSize,
00266 void * pData,
00267 int nBufXSize, int nBufYSize,
00268 GDALDataType eBufType,
00269 int nPixelSpace,
00270 int nLineSpace )
00271
00272 {
00273 GDALRasterBand *poBand = (GDALRasterBand *) hBand;
00274
00275 return( poBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
00276 pData, nBufXSize, nBufYSize, eBufType,
00277 nPixelSpace, nLineSpace ) );
00278 }
00279
00280
00281
00282
00283
00366 CPLErr GDALRasterBand::ReadBlock( int nXBlockOff, int nYBlockOff,
00367 void * pImage )
00368
00369 {
00370
00371
00372
00373 CPLAssert( pImage != NULL );
00374
00375 if( nXBlockOff < 0
00376 || nXBlockOff*nBlockXSize >= nRasterXSize )
00377 {
00378 CPLError( CE_Failure, CPLE_IllegalArg,
00379 "Illegal nXBlockOff value (%d) in "
00380 "GDALRasterBand::ReadBlock()\n",
00381 nXBlockOff );
00382
00383 return( CE_Failure );
00384 }
00385
00386 if( nYBlockOff < 0
00387 || nYBlockOff*nBlockYSize >= nRasterYSize )
00388 {
00389 CPLError( CE_Failure, CPLE_IllegalArg,
00390 "Illegal nYBlockOff value (%d) in "
00391 "GDALRasterBand::ReadBlock()\n",
00392 nYBlockOff );
00393
00394 return( CE_Failure );
00395 }
00396
00397
00398
00399
00400 return( IReadBlock( nXBlockOff, nYBlockOff, pImage ) );
00401 }
00402
00403
00404
00405
00406
00407 CPLErr GDALReadBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
00408 void * pData )
00409
00410 {
00411 GDALRasterBand *poBand = (GDALRasterBand *) hBand;
00412
00413 return( poBand->ReadBlock( nXOff, nYOff, pData ) );
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423 CPLErr GDALRasterBand::IWriteBlock( int, int, void * )
00424
00425 {
00426 CPLError( CE_Failure, CPLE_NotSupported,
00427 "WriteBlock() not supported for this dataset." );
00428
00429 return( CE_Failure );
00430 }
00431
00432
00433
00434
00435
00466 CPLErr GDALRasterBand::WriteBlock( int nXBlockOff, int nYBlockOff,
00467 void * pImage )
00468
00469 {
00470
00471
00472
00473 CPLAssert( pImage != NULL );
00474
00475 if( nXBlockOff < 0
00476 || nXBlockOff*nBlockXSize >= GetXSize() )
00477 {
00478 CPLError( CE_Failure, CPLE_IllegalArg,
00479 "Illegal nXBlockOff value (%d) in "
00480 "GDALRasterBand::WriteBlock()\n",
00481 nXBlockOff );
00482
00483 return( CE_Failure );
00484 }
00485
00486 if( nYBlockOff < 0
00487 || nYBlockOff*nBlockYSize >= GetYSize() )
00488 {
00489 CPLError( CE_Failure, CPLE_IllegalArg,
00490 "Illegal nYBlockOff value (%d) in "
00491 "GDALRasterBand::WriteBlock()\n",
00492 nYBlockOff );
00493
00494 return( CE_Failure );
00495 }
00496
00497 if( eAccess == GA_ReadOnly )
00498 {
00499 CPLError( CE_Failure, CPLE_NoWriteAccess,
00500 "Attempt to write to read only dataset in"
00501 "GDALRasterBand::WriteBlock().\n" );
00502
00503 return( CE_Failure );
00504 }
00505
00506
00507
00508
00509 return( IWriteBlock( nXBlockOff, nYBlockOff, pImage ) );
00510 }
00511
00512
00513
00514
00515
00516 CPLErr GDALWriteBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
00517 void * pData )
00518
00519 {
00520 GDALRasterBand *poBand = (GDALRasterBand *) hBand;
00521
00522 return( poBand->WriteBlock( nXOff, nYOff, pData ) );
00523 }
00524
00525
00526
00527
00528
00529
00537 GDALDataType GDALRasterBand::GetRasterDataType()
00538
00539 {
00540 return eDataType;
00541 }
00542
00543
00544
00545
00546
00547 GDALDataType GDALGetRasterDataType( GDALRasterBandH hBand )
00548
00549 {
00550 return( ((GDALRasterBand *) hBand)->GetRasterDataType() );
00551 }
00552
00553
00554
00555
00556
00577 void GDALRasterBand::GetBlockSize( int * pnXSize, int *pnYSize )
00578
00579 {
00580 CPLAssert( nBlockXSize > 0 && nBlockYSize > 0 );
00581
00582 if( pnXSize != NULL )
00583 *pnXSize = nBlockXSize;
00584 if( pnYSize != NULL )
00585 *pnYSize = nBlockYSize;
00586 }
00587
00588
00589
00590
00591
00592 void GDALGetBlockSize( GDALRasterBandH hBand, int * pnXSize, int * pnYSize )
00593
00594 {
00595 GDALRasterBand *poBand = (GDALRasterBand *) hBand;
00596
00597 poBand->GetBlockSize( pnXSize, pnYSize );
00598 }
00599
00600
00601
00602
00603
00604 void GDALRasterBand::InitBlockInfo()
00605
00606 {
00607 if( papoBlocks != NULL )
00608 return;
00609
00610 CPLAssert( nBlockXSize > 0 && nBlockYSize > 0 );
00611
00612 nBlocksPerRow = (nRasterXSize+nBlockXSize-1) / nBlockXSize;
00613 nBlocksPerColumn = (nRasterYSize+nBlockYSize-1) / nBlockYSize;
00614
00615 papoBlocks = (GDALRasterBlock **)
00616 CPLCalloc( sizeof(void*), nBlocksPerRow * nBlocksPerColumn );
00617 }
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 CPLErr GDALRasterBand::AdoptBlock( int nBlockXOff, int nBlockYOff,
00631 GDALRasterBlock * poBlock )
00632
00633 {
00634 int nBlockIndex;
00635
00636 InitBlockInfo();
00637
00638 CPLAssert( nBlockXOff >= 0 && nBlockXOff < nBlocksPerRow );
00639 CPLAssert( nBlockYOff >= 0 && nBlockYOff < nBlocksPerColumn );
00640
00641 nBlockIndex = nBlockXOff + nBlockYOff * nBlocksPerRow;
00642 if( papoBlocks[nBlockIndex] == poBlock )
00643 return( CE_None );
00644
00645 if( papoBlocks[nBlockIndex] != NULL )
00646 FlushBlock( nBlockXOff, nBlockYOff );
00647
00648 papoBlocks[nBlockIndex] = poBlock;
00649 poBlock->Touch();
00650
00651 return( CE_None );
00652 }
00653
00654
00655
00656
00657
00669 CPLErr GDALRasterBand::FlushCache()
00670
00671 {
00672 for( int iY = 0; iY < nBlocksPerColumn; iY++ )
00673 {
00674 for( int iX = 0; iX < nBlocksPerRow; iX++ )
00675 {
00676 if( papoBlocks[iX + iY*nBlocksPerRow] != NULL )
00677 {
00678 CPLErr eErr;
00679
00680 eErr = FlushBlock( iX, iY );
00681
00682 if( eErr != CE_None )
00683 return eErr;
00684 }
00685 }
00686 }
00687
00688 return( CE_None );
00689 }
00690
00691
00692
00693
00694
00695 CPLErr GDALFlushRasterCache( GDALRasterBandH hBand )
00696
00697 {
00698 return ((GDALRasterBand *) hBand)->FlushCache();
00699 }
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 CPLErr GDALRasterBand::FlushBlock( int nBlockXOff, int nBlockYOff )
00712
00713 {
00714 int nBlockIndex;
00715 GDALRasterBlock *poBlock;
00716 CPLErr eErr = CE_None;
00717
00718 InitBlockInfo();
00719
00720
00721
00722
00723 CPLAssert( nBlockXOff >= 0 && nBlockXOff < nBlocksPerRow );
00724 CPLAssert( nBlockYOff >= 0 && nBlockYOff < nBlocksPerColumn );
00725
00726 nBlockIndex = nBlockXOff + nBlockYOff * nBlocksPerRow;
00727 poBlock = papoBlocks[nBlockIndex];
00728 if( poBlock == NULL )
00729 return( CE_None );
00730
00731
00732
00733
00734 papoBlocks[nBlockIndex] = NULL;
00735
00736
00737
00738
00739 if( poBlock->GetDirty() )
00740 poBlock->Write();
00741
00742
00743
00744
00745 delete poBlock;
00746
00747 return( eErr );
00748 }
00749
00750
00751
00752
00753
00754
00770 GDALRasterBlock * GDALRasterBand::GetBlockRef( int nXBlockOff,
00771 int nYBlockOff )
00772
00773 {
00774 int nBlockIndex;
00775
00776 InitBlockInfo();
00777
00778
00779
00780
00781 if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
00782 {
00783 CPLError( CE_Failure, CPLE_IllegalArg,
00784 "Illegal nBlockXOff value (%d) in "
00785 "GDALRasterBand::GetBlockRef()\n",
00786 nXBlockOff );
00787
00788 return( NULL );
00789 }
00790
00791 if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
00792 {
00793 CPLError( CE_Failure, CPLE_IllegalArg,
00794 "Illegal nBlockYOff value (%d) in "
00795 "GDALRasterBand::GetBlockRef()\n",
00796 nYBlockOff );
00797
00798 return( NULL );
00799 }
00800
00801
00802
00803
00804
00805
00806 nBlockIndex = nXBlockOff + nYBlockOff * nBlocksPerRow;
00807
00808 if( papoBlocks[nBlockIndex] == NULL )
00809 {
00810 GDALRasterBlock *poBlock;
00811
00812 poBlock = new GDALRasterBlock( this, nXBlockOff, nYBlockOff );
00813
00814
00815 if( poBlock->Internalize() != CE_None )
00816 {
00817 delete poBlock;
00818
00819 return( NULL );
00820 }
00821
00822 if( IReadBlock(nXBlockOff,nYBlockOff,poBlock->GetDataRef()) != CE_None)
00823 {
00824 delete poBlock;
00825 return( NULL );
00826 }
00827
00828 AdoptBlock( nXBlockOff, nYBlockOff, poBlock );
00829 }
00830
00831
00832
00833
00834 if( papoBlocks[nBlockIndex] != NULL )
00835 papoBlocks[nBlockIndex]->Touch();
00836
00837 return( papoBlocks[nBlockIndex] );
00838 }
00839
00840
00841
00842
00843
00850 GDALAccess GDALRasterBand::GetAccess()
00851
00852 {
00853 return eAccess;
00854 }
00855
00856
00857
00858
00859
00875 char **GDALRasterBand::GetCategoryNames()
00876
00877 {
00878 return NULL;
00879 }
00880
00881
00882
00883
00884
00885 char **GDALGetRasterCategoryNames( GDALRasterBandH hBand )
00886
00887 {
00888 return ((GDALRasterBand *) hBand)->GetCategoryNames();
00889 }
00890
00891
00892
00893
00894
00910 CPLErr GDALRasterBand::SetCategoryNames( char ** )
00911
00912 {
00913 return CE_Failure;
00914 }
00915
00916
00917
00918
00919
00920 CPLErr GDALSetRasterCategoryNames( GDALRasterBandH hBand, char ** papszNames )
00921
00922 {
00923 return ((GDALRasterBand *) hBand)->SetCategoryNames( papszNames );
00924 }
00925
00926
00927
00928
00929
00946 double GDALRasterBand::GetNoDataValue( int *pbSuccess )
00947
00948 {
00949 if( pbSuccess != NULL )
00950 *pbSuccess = FALSE;
00951
00952 return -1e10;
00953 }
00954
00955
00956
00957
00958
00959 double GDALGetRasterNoDataValue( GDALRasterBandH hBand, int *pbSuccess )
00960
00961 {
00962 return ((GDALRasterBand *) hBand)->GetNoDataValue( pbSuccess );
00963 }
00964
00965
00966
00967
00968
00984 CPLErr GDALRasterBand::SetNoDataValue( double )
00985
00986 {
00987 return CE_Failure;
00988 }
00989
00990
00991
00992
00993
00994 CPLErr GDALSetRasterNoDataValue( GDALRasterBandH hBand, double dfValue )
00995
00996 {
00997 return ((GDALRasterBand *) hBand)->SetNoDataValue( dfValue );
00998 }
00999
01000
01001
01002
01003
01018 double GDALRasterBand::GetMaximum( int *pbSuccess )
01019
01020 {
01021 if( pbSuccess != NULL )
01022 *pbSuccess = FALSE;
01023
01024 switch( eDataType )
01025 {
01026 case GDT_Byte:
01027 return 255;
01028
01029 case GDT_UInt16:
01030 return 65535;
01031
01032 case GDT_Int16:
01033 case GDT_CInt16:
01034 return 32767;
01035
01036 case GDT_Int32:
01037 case GDT_CInt32:
01038 return 2147483647.0;
01039
01040 case GDT_UInt32:
01041 return 4294967295.0;
01042
01043 case GDT_Float32:
01044 case GDT_CFloat32:
01045 return 4294967295.0;
01046
01047 case GDT_Float64:
01048 case GDT_CFloat64:
01049 return 4294967295.0;
01050
01051 default:
01052 return 4294967295.0;
01053 }
01054 }
01055
01056
01057
01058
01059
01060 double GDALGetRasterMaximum( GDALRasterBandH hBand, int *pbSuccess )
01061
01062 {
01063 return ((GDALRasterBand *) hBand)->GetMaximum( pbSuccess );
01064 }
01065
01066
01067
01068
01069
01084 double GDALRasterBand::GetMinimum( int *pbSuccess )
01085
01086 {
01087 if( pbSuccess != NULL )
01088 *pbSuccess = FALSE;
01089
01090 switch( eDataType )
01091 {
01092 case GDT_Byte:
01093 return 0;
01094
01095 case GDT_UInt16:
01096 return 0;
01097
01098 case GDT_Int16:
01099 return -32768;
01100
01101 case GDT_Int32:
01102 return -2147483648.0;
01103
01104 case GDT_UInt32:
01105 return 0;
01106
01107 case GDT_Float32:
01108 return -4294967295.0;
01109
01110 case GDT_Float64:
01111 return -4294967295.0;
01112
01113 default:
01114 return -4294967295.0;
01115 }
01116 }
01117
01118
01119
01120
01121
01122 double GDALGetRasterMinimum( GDALRasterBandH hBand, int *pbSuccess )
01123
01124 {
01125 return ((GDALRasterBand *) hBand)->GetMinimum( pbSuccess );
01126 }
01127
01128
01129
01130
01131
01144 GDALColorInterp GDALRasterBand::GetColorInterpretation()
01145
01146 {
01147 return GCI_Undefined;
01148 }
01149
01150
01151
01152
01153
01154 GDALColorInterp GDALGetRasterColorInterpretation( GDALRasterBandH hBand )
01155
01156 {
01157 return ((GDALRasterBand *) hBand)->GetColorInterpretation();
01158 }
01159
01160
01161
01162
01163
01176 GDALColorTable *GDALRasterBand::GetColorTable()
01177
01178 {
01179 return NULL;
01180 }
01181
01182
01183
01184
01185
01186 GDALColorTableH GDALGetRasterColorTable( GDALRasterBandH hBand )
01187
01188 {
01189 return (GDALColorTableH) ((GDALRasterBand *) hBand)->GetColorTable();
01190 }
01191
01192
01193
01194
01195
01211 CPLErr GDALRasterBand::SetColorTable( GDALColorTable * poCT )
01212
01213 {
01214 return CE_Failure;
01215 }
01216
01217
01218
01219
01220
01221 CPLErr GDALSetRasterColorTable( GDALRasterBandH hBand, GDALColorTableH hCT )
01222
01223 {
01224 return ((GDALRasterBand *) hBand)->SetColorTable( (GDALColorTable *) hCT );
01225 }
01226
01227
01228
01229
01230
01246 int GDALRasterBand::HasArbitraryOverviews()
01247
01248 {
01249 return FALSE;
01250 }
01251
01252
01253
01254
01255
01256 int GDALHasArbitraryOverviews( GDALRasterBandH hBand )
01257
01258 {
01259 return ((GDALRasterBand *) hBand)->HasArbitraryOverviews();
01260 }
01261
01262
01263
01264
01265
01274 int GDALRasterBand::GetOverviewCount()
01275
01276 {
01277 if( poDS != NULL && poDS->oOvManager.IsInitialized() )
01278 return poDS->oOvManager.GetOverviewCount( nBand );
01279 else
01280 return 0;
01281 }
01282
01283
01284
01285
01286
01287 int GDALGetOverviewCount( GDALRasterBandH hBand )
01288
01289 {
01290 return ((GDALRasterBand *) hBand)->GetOverviewCount();
01291 }
01292
01293
01294
01295
01296
01297
01308 GDALRasterBand * GDALRasterBand::GetOverview( int i )
01309
01310 {
01311 if( poDS != NULL && poDS->oOvManager.IsInitialized() )
01312 return poDS->oOvManager.GetOverview( nBand, i );
01313 else
01314 return NULL;
01315 }
01316
01317
01318
01319
01320
01321 GDALRasterBandH GDALGetOverview( GDALRasterBandH hBand, int i )
01322
01323 {
01324 return (GDALRasterBandH) ((GDALRasterBand *) hBand)->GetOverview(i);
01325 }
01326
01327
01328
01329
01330
01347 CPLErr GDALRasterBand::BuildOverviews( const char *pszResampling,
01348 int nOverviews, int *panOverviewList,
01349 GDALProgressFunc pfnProgress,
01350 void * pProgressData )
01351
01352 {
01353 CPLError( CE_Failure, CPLE_NotSupported,
01354 "BuildOverviews() not supported for this dataset." );
01355
01356 return( CE_Failure );
01357 }
01358
01359
01360
01361
01362
01382 double GDALRasterBand::GetOffset( int *pbSuccess )
01383
01384 {
01385 if( pbSuccess != NULL )
01386 *pbSuccess = FALSE;
01387
01388 return 0.0;
01389 }
01390
01391
01392
01393
01394
01414 double GDALRasterBand::GetScale( int *pbSuccess )
01415
01416 {
01417 if( pbSuccess != NULL )
01418 *pbSuccess = FALSE;
01419
01420 return 1.0;
01421 }
01422
01423
01424
01425
01426
01433 const char *GDALRasterBand::GetDescription()
01434
01435 {
01436 return "";
01437 }
01438
01439
01440
01441
01442
01443
01455 const char *GDALRasterBand::GetUnitType()
01456
01457 {
01458 return "";
01459 }
01460
01461
01462
01463
01464
01473 int GDALRasterBand::GetXSize()
01474
01475 {
01476 return nRasterXSize;
01477 }
01478
01479
01480
01481
01482
01483 int GDALGetRasterBandXSize( GDALRasterBandH hBand )
01484
01485 {
01486 return ((GDALRasterBand *) hBand)->GetXSize();
01487 }
01488
01489
01490
01491
01492
01501 int GDALRasterBand::GetYSize()
01502
01503 {
01504 return nRasterYSize;
01505 }
01506
01507
01508
01509
01510
01511 int GDALGetRasterBandYSize( GDALRasterBandH hBand )
01512
01513 {
01514 return ((GDALRasterBand *) hBand)->GetYSize();
01515 }
01516
01517
01518
01519
01520
01557 CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
01558 int nBuckets, int *panHistogram,
01559 int bIncludeOutOfRange, int bApproxOK,
01560 GDALProgressFunc pfnProgress,
01561 void *pProgressData )
01562
01563 {
01564 CPLAssert( pfnProgress != NULL );
01565
01566
01567
01568
01569 if( bApproxOK && GetOverviewCount() > 0 )
01570 {
01571 double dfBestPixels = GetXSize() * GetYSize();
01572 GDALRasterBand *poBestOverview = NULL;
01573
01574 for( int i = 0; i < GetOverviewCount(); i++ )
01575 {
01576 GDALRasterBand *poOverview = GetOverview(i);
01577 double dfPixels;
01578
01579 dfPixels = poOverview->GetXSize() * poOverview->GetYSize();
01580 if( dfPixels < dfBestPixels )
01581 {
01582 dfBestPixels = dfPixels;
01583 poBestOverview = poOverview;
01584 }
01585
01586 if( poBestOverview != NULL )
01587 return poBestOverview->
01588 GetHistogram( dfMin, dfMax, nBuckets, panHistogram,
01589 bIncludeOutOfRange, bApproxOK,
01590 pfnProgress, pProgressData );
01591 }
01592 }
01593
01594
01595
01596
01597
01598 int nBlockXSize, nBlockYSize;
01599 int nBlocksPerRow, nBlocksPerColumn;
01600 int nSampleRate;
01601 double dfScale;
01602
01603 GetBlockSize( &nBlockXSize, &nBlockYSize );
01604 nBlocksPerRow = (GetXSize() + nBlockXSize - 1) / nBlockXSize;
01605 nBlocksPerColumn = (GetYSize() + nBlockYSize - 1) / nBlockYSize;
01606
01607 if( bApproxOK )
01608 nSampleRate =
01609 (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn));
01610 else
01611 nSampleRate = 1;
01612
01613 dfScale = nBuckets / (dfMax - dfMin);
01614
01615
01616
01617
01618 memset( panHistogram, 0, sizeof(int) * nBuckets );
01619 for( int iSampleBlock = 0;
01620 iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
01621 iSampleBlock += nSampleRate )
01622 {
01623 double dfValue = 0.0;
01624 int iXBlock, iYBlock, nXCheck, nYCheck;
01625 GDALRasterBlock *poBlock;
01626
01627 if( !pfnProgress( iSampleBlock/(double)nBlocksPerRow*nBlocksPerColumn,
01628 NULL, pProgressData ) )
01629 return CE_Failure;
01630
01631 iYBlock = iSampleBlock / nBlocksPerRow;
01632 iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
01633
01634 poBlock = GetBlockRef( iXBlock, iYBlock );
01635 if( poBlock == NULL )
01636 return CE_Failure;
01637
01638 if( (iXBlock+1) * nBlockXSize > GetXSize() )
01639 nXCheck = GetXSize() - iXBlock * nBlockXSize;
01640 else
01641 nXCheck = nBlockXSize;
01642
01643 if( (iYBlock+1) * nBlockYSize > GetYSize() )
01644 nYCheck = GetYSize() - iYBlock * nBlockYSize;
01645 else
01646 nYCheck = nBlockYSize;
01647
01648
01649 if( poBlock->GetDataType() == GDT_Byte
01650 && dfScale == 1.0 && (dfMin >= -0.5 && dfMin <= 0.5)
01651 && nYCheck == nBlockYSize && nXCheck == nBlockXSize
01652 && nBuckets == 256 )
01653 {
01654 int nPixels = nXCheck * nYCheck;
01655 GByte *pabyData = (GByte *) poBlock->GetDataRef();
01656
01657 for( int i = 0; i < nPixels; i++ )
01658 panHistogram[pabyData[i]]++;
01659
01660 continue;
01661 }
01662
01663
01664 for( int iY = 0; iY < nYCheck; iY++ )
01665 {
01666 for( int iX = 0; iX < nXCheck; iX++ )
01667 {
01668 int iOffset = iX + iY * nBlockXSize;
01669 int nIndex;
01670
01671 switch( poBlock->GetDataType() )
01672 {
01673 case GDT_Byte:
01674 dfValue = ((GByte *) poBlock->GetDataRef())[iOffset];
01675 break;
01676
01677 case GDT_UInt16:
01678 dfValue = ((GUInt16 *) poBlock->GetDataRef())[iOffset];
01679 break;
01680 case GDT_Int16:
01681 dfValue = ((GInt16 *) poBlock->GetDataRef())[iOffset];
01682 break;
01683 case GDT_UInt32:
01684 dfValue = ((GUInt32 *) poBlock->GetDataRef())[iOffset];
01685 break;
01686 case GDT_Int32:
01687 dfValue = ((GInt32 *) poBlock->GetDataRef())[iOffset];
01688 break;
01689 case GDT_Float32:
01690 dfValue = ((float *) poBlock->GetDataRef())[iOffset];
01691 break;
01692 case GDT_Float64:
01693 dfValue = ((double *) poBlock->GetDataRef())[iOffset];
01694 break;
01695 default:
01696 CPLAssert( FALSE );
01697 return CE_Failure;
01698 }
01699
01700 nIndex = (int) floor((dfValue - dfMin) * dfScale);
01701
01702 if( nIndex < 0 )
01703 {
01704 if( bIncludeOutOfRange )
01705 panHistogram[0]++;
01706 }
01707 else if( nIndex >= nBuckets )
01708 {
01709 if( bIncludeOutOfRange )
01710 panHistogram[nBuckets-1]++;
01711 }
01712 else
01713 {
01714 panHistogram[nIndex]++;
01715 }
01716 }
01717 }
01718 }
01719
01720 pfnProgress( 1.0, NULL, pProgressData );
01721
01722 return CE_None;
01723 }
01724
01725
01726
01727
01728
01729 CPLErr GDALGetRasterHistogram( GDALRasterBandH hBand,
01730 double dfMin, double dfMax,
01731 int nBuckets, int *panHistogram,
01732 int bIncludeOutOfRange, int bApproxOK,
01733 GDALProgressFunc pfnProgress,
01734 void *pProgressData )
01735
01736 {
01737 return ((GDALRasterBand *) hBand)->
01738 GetHistogram( dfMin, dfMax, nBuckets, panHistogram,
01739 bIncludeOutOfRange, bApproxOK,
01740 pfnProgress, pProgressData );
01741 }