LCOV - code coverage report
Current view: directory - gcore - gdalrasterband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1357 845 62.3 %
Date: 2011-12-18 Functions: 105 82 78.1 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdalrasterband.cpp 23425 2011-11-26 19:14:25Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL Core
       5                 :  * Purpose:  Base class for format specific band class implementation.  This
       6                 :  *           base class provides default implementation for many methods.
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 1998, Frank Warmerdam
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "gdal_priv.h"
      32                 : #include "gdal_rat.h"
      33                 : #include "cpl_string.h"
      34                 : 
      35                 : #define SUBBLOCK_SIZE 64
      36                 : #define TO_SUBBLOCK(x) ((x) >> 6)
      37                 : #define WITHIN_SUBBLOCK(x) ((x) & 0x3f)
      38                 : 
      39                 : // Number of data samples that will be used to compute approximate statistics
      40                 : // (minimum value, maximum value, etc.)
      41                 : #define GDALSTAT_APPROX_NUMSAMPLES 2500
      42                 : 
      43                 : CPL_CVSID("$Id: gdalrasterband.cpp 23425 2011-11-26 19:14:25Z rouault $");
      44                 : 
      45                 : /************************************************************************/
      46                 : /*                           GDALRasterBand()                           */
      47                 : /************************************************************************/
      48                 : 
      49                 : /*! Constructor. Applications should never create GDALRasterBands directly. */
      50                 : 
      51          623551 : GDALRasterBand::GDALRasterBand()
      52                 : 
      53                 : {
      54          623551 :     poDS = NULL;
      55          623551 :     nBand = 0;
      56          623551 :     nRasterXSize = nRasterYSize = 0;
      57                 : 
      58          623551 :     eAccess = GA_ReadOnly;
      59          623551 :     nBlockXSize = nBlockYSize = -1;
      60          623551 :     eDataType = GDT_Byte;
      61                 : 
      62          623551 :     nSubBlocksPerRow = nBlocksPerRow = 0;
      63          623551 :     nSubBlocksPerColumn = nBlocksPerColumn = 0;
      64                 : 
      65          623551 :     bSubBlockingActive = FALSE;
      66          623551 :     papoBlocks = NULL;
      67                 : 
      68          623551 :     poMask = NULL;
      69          623551 :     bOwnMask = false;
      70          623551 :     nMaskFlags = 0;
      71                 : 
      72          623551 :     nBlockReads = 0;
      73                 :     bForceCachedIO =  CSLTestBoolean( 
      74          623551 :         CPLGetConfigOption( "GDAL_FORCE_CACHING", "NO") );
      75                 : 
      76          623551 :     eFlushBlockErr = CE_None;
      77          623551 : }
      78                 : 
      79                 : /************************************************************************/
      80                 : /*                          ~GDALRasterBand()                           */
      81                 : /************************************************************************/
      82                 : 
      83                 : /*! Destructor. Applications should never destroy GDALRasterBands directly,
      84                 :     instead destroy the GDALDataset. */
      85                 : 
      86          623551 : GDALRasterBand::~GDALRasterBand()
      87                 : 
      88                 : {
      89          623551 :     FlushCache();
      90                 : 
      91          623551 :     CPLFree( papoBlocks );
      92                 : 
      93          623551 :     if( nBlockReads > nBlocksPerRow * nBlocksPerColumn
      94                 :         && nBand == 1 && poDS != NULL )
      95                 :     {
      96                 :         CPLDebug( "GDAL", "%d block reads on %d block band 1 of %s.",
      97                 :                   nBlockReads, nBlocksPerRow * nBlocksPerColumn, 
      98              75 :                   poDS->GetDescription() );
      99                 :     }
     100                 : 
     101          623551 :     if( bOwnMask )
     102                 :     {
     103            1185 :         delete poMask;
     104            1185 :         poMask = NULL;
     105            1185 :         nMaskFlags = 0;
     106            1185 :         bOwnMask = false;
     107                 :     }
     108          623551 : }
     109                 : 
     110                 : /************************************************************************/
     111                 : /*                              RasterIO()                              */
     112                 : /************************************************************************/
     113                 : 
     114                 : /**
     115                 :  * \brief Read/write a region of image data for this band.
     116                 :  *
     117                 :  * This method allows reading a region of a GDALRasterBand into a buffer,
     118                 :  * or writing data from a buffer into a region of a GDALRasterBand. It
     119                 :  * automatically takes care of data type translation if the data type
     120                 :  * (eBufType) of the buffer is different than that of the GDALRasterBand.
     121                 :  * The method also takes care of image decimation / replication if the
     122                 :  * buffer size (nBufXSize x nBufYSize) is different than the size of the
     123                 :  * region being accessed (nXSize x nYSize).
     124                 :  *
     125                 :  * The nPixelSpace and nLineSpace parameters allow reading into or
     126                 :  * writing from unusually organized buffers. This is primarily used
     127                 :  * for buffers containing more than one bands raster data in interleaved
     128                 :  * format. 
     129                 :  *
     130                 :  * Some formats may efficiently implement decimation into a buffer by
     131                 :  * reading from lower resolution overview images.
     132                 :  *
     133                 :  * For highest performance full resolution data access, read and write
     134                 :  * on "block boundaries" as returned by GetBlockSize(), or use the
     135                 :  * ReadBlock() and WriteBlock() methods.
     136                 :  *
     137                 :  * This method is the same as the C GDALRasterIO() function.
     138                 :  *
     139                 :  * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
     140                 :  * write a region of data.
     141                 :  *
     142                 :  * @param nXOff The pixel offset to the top left corner of the region
     143                 :  * of the band to be accessed. This would be zero to start from the left side.
     144                 :  *
     145                 :  * @param nYOff The line offset to the top left corner of the region
     146                 :  * of the band to be accessed. This would be zero to start from the top.
     147                 :  *
     148                 :  * @param nXSize The width of the region of the band to be accessed in pixels.
     149                 :  *
     150                 :  * @param nYSize The height of the region of the band to be accessed in lines.
     151                 :  *
     152                 :  * @param pData The buffer into which the data should be read, or from which
     153                 :  * it should be written. This buffer must contain at least nBufXSize *
     154                 :  * nBufYSize words of type eBufType. It is organized in left to right,
     155                 :  * top to bottom pixel order. Spacing is controlled by the nPixelSpace,
     156                 :  * and nLineSpace parameters.
     157                 :  *
     158                 :  * @param nBufXSize the width of the buffer image into which the desired region is
     159                 :  * to be read, or from which it is to be written.
     160                 :  *
     161                 :  * @param nBufYSize the height of the buffer image into which the desired region is
     162                 :  * to be read, or from which it is to be written.
     163                 :  *
     164                 :  * @param eBufType the type of the pixel values in the pData data buffer. The
     165                 :  * pixel values will automatically be translated to/from the GDALRasterBand
     166                 :  * data type as needed.
     167                 :  *
     168                 :  * @param nPixelSpace The byte offset from the start of one pixel value in
     169                 :  * pData to the start of the next pixel value within a scanline. If defaulted
     170                 :  * (0) the size of the datatype eBufType is used.
     171                 :  *
     172                 :  * @param nLineSpace The byte offset from the start of one scanline in
     173                 :  * pData to the start of the next. If defaulted (0) the size of the datatype
     174                 :  * eBufType * nBufXSize is used.
     175                 :  *
     176                 :  * @return CE_Failure if the access fails, otherwise CE_None.
     177                 :  */
     178                 : 
     179          600335 : CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
     180                 :                                  int nXOff, int nYOff, int nXSize, int nYSize,
     181                 :                                  void * pData, int nBufXSize, int nBufYSize,
     182                 :                                  GDALDataType eBufType,
     183                 :                                  int nPixelSpace,
     184                 :                                  int nLineSpace )
     185                 : 
     186                 : {
     187                 : 
     188          600335 :     if( NULL == pData )
     189                 :     {
     190                 :         ReportError( CE_Failure, CPLE_AppDefined,
     191               0 :                   "The buffer into which the data should be read is null" );
     192               0 :             return CE_Failure;
     193                 :     }
     194                 : 
     195                 : /* -------------------------------------------------------------------- */
     196                 : /*      Some size values are "noop".  Lets just return to avoid         */
     197                 : /*      stressing lower level functions.                                */
     198                 : /* -------------------------------------------------------------------- */
     199          600335 :     if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
     200                 :     {
     201                 :         CPLDebug( "GDAL", 
     202                 :                   "RasterIO() skipped for odd window or buffer size.\n"
     203                 :                   "  Window = (%d,%d)x%dx%d\n"
     204                 :                   "  Buffer = %dx%d\n",
     205                 :                   nXOff, nYOff, nXSize, nYSize, 
     206               0 :                   nBufXSize, nBufYSize );
     207                 : 
     208               0 :         return CE_None;
     209                 :     }
     210                 : 
     211          600335 :     if( eRWFlag == GF_Write && eFlushBlockErr != CE_None )
     212                 :     {
     213                 :         ReportError(eFlushBlockErr, CPLE_AppDefined,
     214               0 :                  "An error occured while writing a dirty block");
     215               0 :         CPLErr eErr = eFlushBlockErr;
     216               0 :         eFlushBlockErr = CE_None;
     217               0 :         return eErr;
     218                 :     }
     219                 : 
     220                 : /* -------------------------------------------------------------------- */
     221                 : /*      If pixel and line spaceing are defaulted assign reasonable      */
     222                 : /*      value assuming a packed buffer.                                 */
     223                 : /* -------------------------------------------------------------------- */
     224          600335 :     if( nPixelSpace == 0 )
     225          570569 :         nPixelSpace = GDALGetDataTypeSize( eBufType ) / 8;
     226                 :     
     227          600335 :     if( nLineSpace == 0 )
     228                 :     {
     229          571774 :         if (nPixelSpace > INT_MAX / nBufXSize)
     230                 :         {
     231                 :             ReportError( CE_Failure, CPLE_AppDefined,
     232               0 :                       "Int overflow : %d x %d", nPixelSpace, nBufXSize );
     233               0 :             return CE_Failure;
     234                 :         }
     235          571774 :         nLineSpace = nPixelSpace * nBufXSize;
     236                 :     }
     237                 :     
     238                 : /* -------------------------------------------------------------------- */
     239                 : /*      Do some validation of parameters.                               */
     240                 : /* -------------------------------------------------------------------- */
     241          600335 :     if( nXOff < 0 || nXOff > INT_MAX - nXSize || nXOff + nXSize > nRasterXSize
     242                 :         || nYOff < 0 || nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize )
     243                 :     {
     244                 :         ReportError( CE_Failure, CPLE_IllegalArg,
     245                 :                   "Access window out of range in RasterIO().  Requested\n"
     246                 :                   "(%d,%d) of size %dx%d on raster of %dx%d.",
     247           13213 :                   nXOff, nYOff, nXSize, nYSize, nRasterXSize, nRasterYSize );
     248           13213 :         return CE_Failure;
     249                 :     }
     250                 : 
     251          587122 :     if( eRWFlag != GF_Read && eRWFlag != GF_Write )
     252                 :     {
     253                 :         ReportError( CE_Failure, CPLE_IllegalArg,
     254                 :                   "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
     255               0 :                   eRWFlag );
     256               0 :         return CE_Failure;
     257                 :     }
     258                 : 
     259                 : /* -------------------------------------------------------------------- */
     260                 : /*      Call the format specific function.                              */
     261                 : /* -------------------------------------------------------------------- */
     262          587122 :     if( bForceCachedIO )
     263                 :         return GDALRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
     264                 :                                          pData, nBufXSize, nBufYSize, eBufType,
     265              22 :                                          nPixelSpace, nLineSpace );
     266                 :     else
     267                 :         return IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
     268                 :                           pData, nBufXSize, nBufYSize, eBufType,
     269          587100 :                           nPixelSpace, nLineSpace ) ;
     270                 : }
     271                 : 
     272                 : /************************************************************************/
     273                 : /*                            GDALRasterIO()                            */
     274                 : /************************************************************************/
     275                 : 
     276                 : /**
     277                 :  * \brief Read/write a region of image data for this band.
     278                 :  *
     279                 :  * @see GDALRasterBand::RasterIO()
     280                 :  */
     281                 : 
     282                 : CPLErr CPL_STDCALL 
     283          414906 : GDALRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
     284                 :               int nXOff, int nYOff, int nXSize, int nYSize,
     285                 :               void * pData, int nBufXSize, int nBufYSize,
     286                 :               GDALDataType eBufType,
     287                 :               int nPixelSpace, int nLineSpace )
     288                 :     
     289                 : {
     290          414906 :     VALIDATE_POINTER1( hBand, "GDALRasterIO", CE_Failure );
     291                 : 
     292          414906 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
     293                 : 
     294                 :     return( poBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
     295                 :                               pData, nBufXSize, nBufYSize, eBufType,
     296          414906 :                               nPixelSpace, nLineSpace ) );
     297                 : }
     298                 :                      
     299                 : /************************************************************************/
     300                 : /*                             ReadBlock()                              */
     301                 : /************************************************************************/
     302                 : 
     303                 : /**
     304                 :  * \brief Read a block of image data efficiently.
     305                 :  *
     306                 :  * This method accesses a "natural" block from the raster band without
     307                 :  * resampling, or data type conversion.  For a more generalized, but
     308                 :  * potentially less efficient access use RasterIO().
     309                 :  *
     310                 :  * This method is the same as the C GDALReadBlock() function.
     311                 :  *
     312                 :  * See the GetLockedBlockRef() method for a way of accessing internally cached
     313                 :  * block oriented data without an extra copy into an application buffer.
     314                 :  *
     315                 :  * @param nXBlockOff the horizontal block offset, with zero indicating
     316                 :  * the left most block, 1 the next block and so forth. 
     317                 :  *
     318                 :  * @param nYBlockOff the vertical block offset, with zero indicating
     319                 :  * the left most block, 1 the next block and so forth.
     320                 :  *
     321                 :  * @param pImage the buffer into which the data will be read.  The buffer
     322                 :  * must be large enough to hold GetBlockXSize()*GetBlockYSize() words
     323                 :  * of type GetRasterDataType().
     324                 :  *
     325                 :  * @return CE_None on success or CE_Failure on an error.
     326                 :  *
     327                 :  * The following code would efficiently compute a histogram of eight bit
     328                 :  * raster data.  Note that the final block may be partial ... data beyond
     329                 :  * the edge of the underlying raster band in these edge blocks is of an
     330                 :  * undermined value.
     331                 :  *
     332                 : <pre>
     333                 :  CPLErr GetHistogram( GDALRasterBand *poBand, int *panHistogram )
     334                 : 
     335                 :  {
     336                 :      int        nXBlocks, nYBlocks, nXBlockSize, nYBlockSize;
     337                 :      int        iXBlock, iYBlock;
     338                 :      GByte      *pabyData;
     339                 : 
     340                 :      memset( panHistogram, 0, sizeof(int) * 256 );
     341                 : 
     342                 :      CPLAssert( poBand->GetRasterDataType() == GDT_Byte );
     343                 : 
     344                 :      poBand->GetBlockSize( &nXBlockSize, &nYBlockSize );
     345                 :      nXBlocks = (poBand->GetXSize() + nXBlockSize - 1) / nXBlockSize;
     346                 :      nYBlocks = (poBand->GetYSize() + nYBlockSize - 1) / nYBlockSize;
     347                 : 
     348                 :      pabyData = (GByte *) CPLMalloc(nXBlockSize * nYBlockSize);
     349                 : 
     350                 :      for( iYBlock = 0; iYBlock < nYBlocks; iYBlock++ )
     351                 :      {
     352                 :          for( iXBlock = 0; iXBlock < nXBlocks; iXBlock++ )
     353                 :          {
     354                 :              int        nXValid, nYValid;
     355                 :              
     356                 :              poBand->ReadBlock( iXBlock, iYBlock, pabyData );
     357                 : 
     358                 :              // Compute the portion of the block that is valid
     359                 :              // for partial edge blocks.
     360                 :              if( (iXBlock+1) * nXBlockSize > poBand->GetXSize() )
     361                 :                  nXValid = poBand->GetXSize() - iXBlock * nXBlockSize;
     362                 :              else
     363                 :                  nXValid = nXBlockSize;
     364                 : 
     365                 :              if( (iYBlock+1) * nYBlockSize > poBand->GetYSize() )
     366                 :                  nYValid = poBand->GetYSize() - iYBlock * nYBlockSize;
     367                 :              else
     368                 :                  nYValid = nYBlockSize;
     369                 : 
     370                 :              // Collect the histogram counts.
     371                 :              for( int iY = 0; iY < nYValid; iY++ )
     372                 :              {
     373                 :                  for( int iX = 0; iX < nXValid; iX++ )
     374                 :                  {
     375                 :                      panHistogram[pabyData[iX + iY * nXBlockSize]] += 1;
     376                 :                  }
     377                 :              }
     378                 :          }
     379                 :      }
     380                 :  }
     381                 :  
     382                 : </pre>
     383                 :  */
     384                 : 
     385                 : 
     386             180 : CPLErr GDALRasterBand::ReadBlock( int nXBlockOff, int nYBlockOff,
     387                 :                                    void * pImage )
     388                 : 
     389                 : {
     390                 : /* -------------------------------------------------------------------- */
     391                 : /*      Validate arguments.                                             */
     392                 : /* -------------------------------------------------------------------- */
     393             180 :     CPLAssert( pImage != NULL );
     394                 :     
     395             180 :     if( !InitBlockInfo() )
     396               0 :         return CE_Failure;
     397                 :         
     398             180 :     if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
     399                 :     {
     400                 :         ReportError( CE_Failure, CPLE_IllegalArg,
     401                 :                   "Illegal nXBlockOff value (%d) in "
     402                 :                         "GDALRasterBand::ReadBlock()\n",
     403               0 :                   nXBlockOff );
     404                 : 
     405               0 :         return( CE_Failure );
     406                 :     }
     407                 : 
     408             180 :     if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
     409                 :     {
     410                 :         ReportError( CE_Failure, CPLE_IllegalArg,
     411                 :                   "Illegal nYBlockOff value (%d) in "
     412                 :                         "GDALRasterBand::ReadBlock()\n",
     413               0 :                   nYBlockOff );
     414                 : 
     415               0 :         return( CE_Failure );
     416                 :     }
     417                 : 
     418                 : /* -------------------------------------------------------------------- */
     419                 : /*      Invoke underlying implementation method.                        */
     420                 : /* -------------------------------------------------------------------- */
     421             180 :     return( IReadBlock( nXBlockOff, nYBlockOff, pImage ) );
     422                 : }
     423                 : 
     424                 : /************************************************************************/
     425                 : /*                           GDALReadBlock()                            */
     426                 : /************************************************************************/
     427                 : 
     428                 : /**
     429                 :  * \brief Read a block of image data efficiently.
     430                 :  *
     431                 :  * @see GDALRasterBand::ReadBlock()
     432                 :  */
     433                 : 
     434               0 : CPLErr CPL_STDCALL GDALReadBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
     435                 :                       void * pData )
     436                 : 
     437                 : {
     438               0 :     VALIDATE_POINTER1( hBand, "GDALReadBlock", CE_Failure );
     439                 : 
     440               0 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
     441               0 :     return( poBand->ReadBlock( nXOff, nYOff, pData ) );
     442                 : }
     443                 : 
     444                 : /************************************************************************/
     445                 : /*                            IWriteBlock()                             */
     446                 : /*                                                                      */
     447                 : /*      Default internal implementation ... to be overriden by          */
     448                 : /*      subclasses that support writing.                                */
     449                 : /************************************************************************/
     450                 : 
     451               0 : CPLErr GDALRasterBand::IWriteBlock( int, int, void * )
     452                 : 
     453                 : {
     454               0 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
     455                 :         ReportError( CE_Failure, CPLE_NotSupported,
     456               0 :                   "WriteBlock() not supported for this dataset." );
     457                 :     
     458               0 :     return( CE_Failure );
     459                 : }
     460                 : 
     461                 : /************************************************************************/
     462                 : /*                             WriteBlock()                             */
     463                 : /************************************************************************/
     464                 : 
     465                 : /**
     466                 :  * \brief Write a block of image data efficiently.
     467                 :  *
     468                 :  * This method accesses a "natural" block from the raster band without
     469                 :  * resampling, or data type conversion.  For a more generalized, but
     470                 :  * potentially less efficient access use RasterIO().
     471                 :  *
     472                 :  * This method is the same as the C GDALWriteBlock() function.
     473                 :  *
     474                 :  * See ReadBlock() for an example of block oriented data access.
     475                 :  *
     476                 :  * @param nXBlockOff the horizontal block offset, with zero indicating
     477                 :  * the left most block, 1 the next block and so forth. 
     478                 :  *
     479                 :  * @param nYBlockOff the vertical block offset, with zero indicating
     480                 :  * the left most block, 1 the next block and so forth.
     481                 :  *
     482                 :  * @param pImage the buffer from which the data will be written.  The buffer
     483                 :  * must be large enough to hold GetBlockXSize()*GetBlockYSize() words
     484                 :  * of type GetRasterDataType().
     485                 :  *
     486                 :  * @return CE_None on success or CE_Failure on an error.
     487                 :  */
     488                 : 
     489               0 : CPLErr GDALRasterBand::WriteBlock( int nXBlockOff, int nYBlockOff,
     490                 :                                    void * pImage )
     491                 : 
     492                 : {
     493                 : /* -------------------------------------------------------------------- */
     494                 : /*      Validate arguments.                                             */
     495                 : /* -------------------------------------------------------------------- */
     496               0 :     CPLAssert( pImage != NULL );
     497                 : 
     498               0 :     if( !InitBlockInfo() )
     499               0 :         return CE_Failure;
     500                 : 
     501               0 :     if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
     502                 :     {
     503                 :         ReportError( CE_Failure, CPLE_IllegalArg,
     504                 :                   "Illegal nXBlockOff value (%d) in "
     505                 :                         "GDALRasterBand::WriteBlock()\n",
     506               0 :                   nXBlockOff );
     507                 : 
     508               0 :         return( CE_Failure );
     509                 :     }
     510                 : 
     511               0 :     if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
     512                 :     {
     513                 :         ReportError( CE_Failure, CPLE_IllegalArg,
     514                 :                   "Illegal nYBlockOff value (%d) in "
     515                 :                         "GDALRasterBand::WriteBlock()\n",
     516               0 :                   nYBlockOff );
     517                 : 
     518               0 :         return( CE_Failure );
     519                 :     }
     520                 : 
     521               0 :     if( eAccess == GA_ReadOnly )
     522                 :     {
     523                 :         ReportError( CE_Failure, CPLE_NoWriteAccess,
     524                 :                   "Attempt to write to read only dataset in"
     525               0 :                   "GDALRasterBand::WriteBlock().\n" );
     526                 : 
     527               0 :         return( CE_Failure );
     528                 :     }
     529                 : 
     530               0 :     if( eFlushBlockErr != CE_None )
     531                 :     {
     532                 :         ReportError(eFlushBlockErr, CPLE_AppDefined,
     533               0 :                  "An error occured while writing a dirty block");
     534               0 :         CPLErr eErr = eFlushBlockErr;
     535               0 :         eFlushBlockErr = CE_None;
     536               0 :         return eErr;
     537                 :     }
     538                 : 
     539                 : /* -------------------------------------------------------------------- */
     540                 : /*      Invoke underlying implementation method.                        */
     541                 : /* -------------------------------------------------------------------- */
     542               0 :     return( IWriteBlock( nXBlockOff, nYBlockOff, pImage ) );
     543                 : }
     544                 : 
     545                 : /************************************************************************/
     546                 : /*                           GDALWriteBlock()                           */
     547                 : /************************************************************************/
     548                 : 
     549                 : /**
     550                 :  * \brief Write a block of image data efficiently.
     551                 :  *
     552                 :  * @see GDALRasterBand::WriteBlock()
     553                 :  */
     554                 : 
     555               0 : CPLErr CPL_STDCALL GDALWriteBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
     556                 :                        void * pData )
     557                 : 
     558                 : {
     559               0 :     VALIDATE_POINTER1( hBand, "GDALWriteBlock", CE_Failure );
     560                 : 
     561               0 :     GDALRasterBand *poBand = static_cast<GDALRasterBand *>( hBand );
     562               0 :     return( poBand->WriteBlock( nXOff, nYOff, pData ) );
     563                 : }
     564                 : 
     565                 : 
     566                 : /************************************************************************/
     567                 : /*                         GetRasterDataType()                          */
     568                 : /************************************************************************/
     569                 : 
     570                 : /**
     571                 :  * \brief Fetch the pixel data type for this band.
     572                 :  *
     573                 :  * @return the data type of pixels for this band.
     574                 :  */
     575                 :   
     576                 : 
     577          703323 : GDALDataType GDALRasterBand::GetRasterDataType()
     578                 : 
     579                 : {
     580          703323 :     return eDataType;
     581                 : }
     582                 : 
     583                 : /************************************************************************/
     584                 : /*                       GDALGetRasterDataType()                        */
     585                 : /************************************************************************/
     586                 : 
     587                 : /**
     588                 :  * \brief Fetch the pixel data type for this band.
     589                 :  *
     590                 :  * @see GDALRasterBand::GetRasterDataType()
     591                 :  */
     592                 : 
     593            5210 : GDALDataType CPL_STDCALL GDALGetRasterDataType( GDALRasterBandH hBand )
     594                 : 
     595                 : {
     596            5210 :     VALIDATE_POINTER1( hBand, "GDALGetRasterDataType", GDT_Unknown );
     597                 : 
     598            5210 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
     599            5210 :     return poBand->GetRasterDataType();
     600                 : }
     601                 : 
     602                 : /************************************************************************/
     603                 : /*                            GetBlockSize()                            */
     604                 : /************************************************************************/
     605                 : 
     606                 : /**
     607                 :  * \brief Fetch the "natural" block size of this band.
     608                 :  *
     609                 :  * GDAL contains a concept of the natural block size of rasters so that
     610                 :  * applications can organized data access efficiently for some file formats.
     611                 :  * The natural block size is the block size that is most efficient for
     612                 :  * accessing the format.  For many formats this is simple a whole scanline
     613                 :  * in which case *pnXSize is set to GetXSize(), and *pnYSize is set to 1.
     614                 :  *
     615                 :  * However, for tiled images this will typically be the tile size.
     616                 :  *
     617                 :  * Note that the X and Y block sizes don't have to divide the image size
     618                 :  * evenly, meaning that right and bottom edge blocks may be incomplete.
     619                 :  * See ReadBlock() for an example of code dealing with these issues.
     620                 :  *
     621                 :  * @param pnXSize integer to put the X block size into or NULL.
     622                 :  *
     623                 :  * @param pnYSize integer to put the Y block size into or NULL.
     624                 :  */
     625                 : 
     626          375616 : void GDALRasterBand::GetBlockSize( int * pnXSize, int *pnYSize )
     627                 : 
     628                 : {
     629          375616 :     if( nBlockXSize <= 0 || nBlockYSize <= 0 )
     630                 :     {
     631                 :         ReportError( CE_Failure, CPLE_AppDefined, "Invalid block dimension : %d * %d",
     632               0 :                  nBlockXSize, nBlockYSize );
     633               0 :         if( pnXSize != NULL )
     634               0 :             *pnXSize = 0;
     635               0 :         if( pnYSize != NULL )
     636               0 :             *pnYSize = 0;
     637                 :     }
     638                 :     else
     639                 :     {
     640          375616 :         if( pnXSize != NULL )
     641          375616 :             *pnXSize = nBlockXSize;
     642          375616 :         if( pnYSize != NULL )
     643          375616 :             *pnYSize = nBlockYSize;
     644                 :     }
     645          375616 : }
     646                 : 
     647                 : /************************************************************************/
     648                 : /*                          GDALGetBlockSize()                          */
     649                 : /************************************************************************/
     650                 : 
     651                 : /**
     652                 :  * \brief Fetch the "natural" block size of this band.
     653                 :  *
     654                 :  * @see GDALRasterBand::GetBlockSize()
     655                 :  */
     656                 : 
     657                 : void CPL_STDCALL 
     658             848 : GDALGetBlockSize( GDALRasterBandH hBand, int * pnXSize, int * pnYSize )
     659                 : 
     660                 : {
     661             848 :     VALIDATE_POINTER0( hBand, "GDALGetBlockSize" );
     662                 : 
     663             848 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
     664             848 :     poBand->GetBlockSize( pnXSize, pnYSize );
     665                 : }
     666                 : 
     667                 : /************************************************************************/
     668                 : /*                           InitBlockInfo()                            */
     669                 : /************************************************************************/
     670                 : 
     671         5308542 : int GDALRasterBand::InitBlockInfo()
     672                 : 
     673                 : {
     674         5308542 :     if( papoBlocks != NULL )
     675         5236780 :         return TRUE;
     676                 : 
     677                 :     /* Do some validation of raster and block dimensions in case the driver */
     678                 :     /* would have neglected to do it itself */
     679           71762 :     if( nBlockXSize <= 0 || nBlockYSize <= 0 )
     680                 :     {
     681                 :         ReportError( CE_Failure, CPLE_AppDefined, "Invalid block dimension : %d * %d",
     682               0 :                   nBlockXSize, nBlockYSize );
     683               0 :         return FALSE;
     684                 :     }
     685                 : 
     686           71762 :     if( nRasterXSize <= 0 || nRasterYSize <= 0 )
     687                 :     {
     688                 :         ReportError( CE_Failure, CPLE_AppDefined, "Invalid raster dimension : %d * %d",
     689               0 :                   nRasterXSize, nRasterYSize );
     690               0 :         return FALSE;
     691                 :     }
     692                 : 
     693           71762 :     if (nBlockXSize >= 10000 || nBlockYSize >= 10000)
     694                 :     {
     695                 :         /* Check that the block size is not overflowing int capacity as it is */
     696                 :         /* (reasonnably) assumed in many places (GDALRasterBlock::Internalize(), */
     697                 :         /* GDALRasterBand::Fill(), many drivers...) */
     698                 :         /* As 10000 * 10000 * 16 < INT_MAX, we don't need to do the multiplication in other cases */
     699                 : 
     700               7 :         int nSizeInBytes = nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
     701                 : 
     702               7 :         GIntBig nBigSizeInBytes = (GIntBig)nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
     703               7 :         if ((GIntBig)nSizeInBytes != nBigSizeInBytes)
     704                 :         {
     705                 :             ReportError( CE_Failure, CPLE_NotSupported, "Too big block : %d * %d",
     706               0 :                         nBlockXSize, nBlockYSize );
     707               0 :             return FALSE;
     708                 :         }
     709                 :     }
     710                 : 
     711                 :     /* Check for overflows in computation of nBlocksPerRow and nBlocksPerColumn */
     712           71762 :     if (nRasterXSize > INT_MAX - (nBlockXSize-1))
     713                 :     {
     714                 :         ReportError( CE_Failure, CPLE_NotSupported, "Inappropriate raster width (%d) for block width (%d)",
     715               0 :                     nRasterXSize, nBlockXSize );
     716               0 :         return FALSE;
     717                 :     }
     718                 : 
     719           71762 :     if (nRasterYSize > INT_MAX - (nBlockYSize-1))
     720                 :     {
     721                 :         ReportError( CE_Failure, CPLE_NotSupported, "Inappropriate raster height (%d) for block height (%d)",
     722               0 :                     nRasterYSize, nBlockYSize );
     723               0 :         return FALSE;
     724                 :     }
     725                 : 
     726           71762 :     nBlocksPerRow = (nRasterXSize+nBlockXSize-1) / nBlockXSize;
     727           71762 :     nBlocksPerColumn = (nRasterYSize+nBlockYSize-1) / nBlockYSize;
     728                 :     
     729           71762 :     if( nBlocksPerRow < SUBBLOCK_SIZE/2 )
     730                 :     {
     731           71714 :         bSubBlockingActive = FALSE;
     732                 : 
     733           71714 :         if (nBlocksPerRow < INT_MAX / nBlocksPerColumn)
     734                 :         {
     735                 :             papoBlocks = (GDALRasterBlock **)
     736           71714 :                 VSICalloc( sizeof(void*), nBlocksPerRow * nBlocksPerColumn );
     737                 :         }
     738                 :         else
     739                 :         {
     740                 :             ReportError( CE_Failure, CPLE_NotSupported, "Too many blocks : %d x %d",
     741               0 :                      nBlocksPerRow, nBlocksPerColumn );
     742               0 :             return FALSE;
     743                 :         }
     744                 :     }
     745                 :     else
     746                 :     {
     747                 :         /* Check for overflows in computation of nSubBlocksPerRow and nSubBlocksPerColumn */
     748              48 :         if (nBlocksPerRow > INT_MAX - (SUBBLOCK_SIZE+1))
     749                 :         {
     750                 :             ReportError( CE_Failure, CPLE_NotSupported, "Inappropriate raster width (%d) for block width (%d)",
     751               0 :                         nRasterXSize, nBlockXSize );
     752               0 :             return FALSE;
     753                 :         }
     754                 : 
     755              48 :         if (nBlocksPerColumn > INT_MAX - (SUBBLOCK_SIZE+1))
     756                 :         {
     757                 :             ReportError( CE_Failure, CPLE_NotSupported, "Inappropriate raster height (%d) for block height (%d)",
     758               0 :                         nRasterYSize, nBlockYSize );
     759               0 :             return FALSE;
     760                 :         }
     761                 : 
     762              48 :         bSubBlockingActive = TRUE;
     763                 : 
     764              48 :         nSubBlocksPerRow = (nBlocksPerRow + SUBBLOCK_SIZE + 1)/SUBBLOCK_SIZE;
     765              48 :         nSubBlocksPerColumn = (nBlocksPerColumn + SUBBLOCK_SIZE + 1)/SUBBLOCK_SIZE;
     766                 : 
     767              48 :         if (nSubBlocksPerRow < INT_MAX / nSubBlocksPerColumn)
     768                 :         {
     769                 :             papoBlocks = (GDALRasterBlock **)
     770              48 :                 VSICalloc( sizeof(void*), nSubBlocksPerRow * nSubBlocksPerColumn );
     771                 :         }
     772                 :         else
     773                 :         {
     774                 :             ReportError( CE_Failure, CPLE_NotSupported, "Too many subblocks : %d x %d",
     775               0 :                       nSubBlocksPerRow, nSubBlocksPerColumn );
     776               0 :             return FALSE;
     777                 :         }
     778                 :     }
     779                 : 
     780           71762 :     if( papoBlocks == NULL )
     781                 :     {
     782                 :         ReportError( CE_Failure, CPLE_OutOfMemory,
     783               0 :                   "Out of memory in InitBlockInfo()." );
     784               0 :         return FALSE;
     785                 :     }
     786                 : 
     787           71762 :     return TRUE;
     788                 : }
     789                 : 
     790                 : /************************************************************************/
     791                 : /*                             AdoptBlock()                             */
     792                 : /*                                                                      */
     793                 : /*      Add a block to the raster band's block matrix.  If this         */
     794                 : /*      exceeds our maximum blocks for this layer, flush the oldest     */
     795                 : /*      block out.                                                      */
     796                 : /*                                                                      */
     797                 : /*      This method is protected.                                       */
     798                 : /************************************************************************/
     799                 : 
     800          367941 : CPLErr GDALRasterBand::AdoptBlock( int nXBlockOff, int nYBlockOff,
     801                 :                                    GDALRasterBlock * poBlock )
     802                 : 
     803                 : {
     804                 :     int         nBlockIndex;
     805                 :     
     806          367941 :     if( !InitBlockInfo() )
     807               0 :         return CE_Failure;
     808                 :     
     809                 : /* -------------------------------------------------------------------- */
     810                 : /*      Simple case without subblocking.                                */
     811                 : /* -------------------------------------------------------------------- */
     812          367941 :     if( !bSubBlockingActive )
     813                 :     {
     814          347067 :         nBlockIndex = nXBlockOff + nYBlockOff * nBlocksPerRow;
     815                 : 
     816          347067 :         if( papoBlocks[nBlockIndex] == poBlock )
     817               0 :             return( CE_None );
     818                 : 
     819          347067 :         if( papoBlocks[nBlockIndex] != NULL )
     820               0 :             FlushBlock( nXBlockOff, nYBlockOff );
     821                 : 
     822          347067 :         papoBlocks[nBlockIndex] = poBlock;
     823          347067 :         poBlock->Touch();
     824                 : 
     825          347067 :         return( CE_None );
     826                 :     }
     827                 : 
     828                 : /* -------------------------------------------------------------------- */
     829                 : /*      Identify the subblock in which our target occurs, and create    */
     830                 : /*      it if necessary.                                                */
     831                 : /* -------------------------------------------------------------------- */
     832                 :     int nSubBlock = TO_SUBBLOCK(nXBlockOff) 
     833           20874 :         + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
     834                 : 
     835           20874 :     if( papoBlocks[nSubBlock] == NULL )
     836                 :     {
     837                 :         const int nSubGridSize = 
     838              93 :             sizeof(GDALRasterBlock*) * SUBBLOCK_SIZE * SUBBLOCK_SIZE;
     839                 : 
     840              93 :         papoBlocks[nSubBlock] = (GDALRasterBlock *) VSICalloc(1, nSubGridSize);
     841              93 :         if( papoBlocks[nSubBlock] == NULL )
     842                 :         {
     843                 :             ReportError( CE_Failure, CPLE_OutOfMemory,
     844               0 :                       "Out of memory in AdoptBlock()." );
     845               0 :             return CE_Failure;
     846                 :         }
     847                 :     }
     848                 : 
     849                 : /* -------------------------------------------------------------------- */
     850                 : /*      Check within subblock.                                          */
     851                 : /* -------------------------------------------------------------------- */
     852                 :     GDALRasterBlock **papoSubBlockGrid = 
     853           20874 :         (GDALRasterBlock **) papoBlocks[nSubBlock];
     854                 : 
     855                 :     int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
     856           20874 :         + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
     857                 : 
     858           20874 :     if( papoSubBlockGrid[nBlockInSubBlock] == poBlock )
     859               0 :         return CE_None;
     860                 : 
     861           20874 :     if( papoSubBlockGrid[nBlockInSubBlock] != NULL )
     862               0 :         FlushBlock( nXBlockOff, nYBlockOff );
     863                 : 
     864           20874 :     papoSubBlockGrid[nBlockInSubBlock] = poBlock;
     865           20874 :     poBlock->Touch();
     866                 : 
     867           20874 :     return CE_None;
     868                 : }
     869                 : 
     870                 : /************************************************************************/
     871                 : /*                             FlushCache()                             */
     872                 : /************************************************************************/
     873                 : 
     874                 : /**
     875                 :  * \brief Flush raster data cache.
     876                 :  *
     877                 :  * This call will recover memory used to cache data blocks for this raster
     878                 :  * band, and ensure that new requests are referred to the underlying driver.
     879                 :  *
     880                 :  * This method is the same as the C function GDALFlushRasterCache().
     881                 :  *
     882                 :  * @return CE_None on success.
     883                 :  */
     884                 : 
     885         1648306 : CPLErr GDALRasterBand::FlushCache()
     886                 : 
     887                 : {
     888         1648306 :     CPLErr eGlobalErr = eFlushBlockErr;
     889                 : 
     890         1648306 :     if (eFlushBlockErr != CE_None)
     891                 :     {
     892                 :         ReportError(eFlushBlockErr, CPLE_AppDefined,
     893               0 :                  "An error occured while writing a dirty block");
     894               0 :         eFlushBlockErr = CE_None;
     895                 :     }
     896                 : 
     897         1648306 :     if (papoBlocks == NULL)
     898         1433357 :         return eGlobalErr;
     899                 : 
     900                 : /* -------------------------------------------------------------------- */
     901                 : /*      Flush all blocks in memory ... this case is without subblocking.*/
     902                 : /* -------------------------------------------------------------------- */
     903          214949 :     if( !bSubBlockingActive )
     904                 :     {
     905         1712093 :         for( int iY = 0; iY < nBlocksPerColumn; iY++ )
     906                 :         {
     907         3029410 :             for( int iX = 0; iX < nBlocksPerRow; iX++ )
     908                 :             {
     909         1532163 :                 if( papoBlocks[iX + iY*nBlocksPerRow] != NULL )
     910                 :                 {
     911                 :                     CPLErr    eErr;
     912                 : 
     913          339164 :                     eErr = FlushBlock( iX, iY, eGlobalErr == CE_None );
     914                 : 
     915          339164 :                     if( eErr != CE_None )
     916               1 :                         eGlobalErr = eErr;
     917                 :                 }
     918                 :             }
     919                 :         }
     920          214846 :         return eGlobalErr;
     921                 :     }
     922                 : 
     923                 : /* -------------------------------------------------------------------- */
     924                 : /*      With subblocking.  We can short circuit missing subblocks.      */
     925                 : /* -------------------------------------------------------------------- */
     926                 :     int iSBX, iSBY;
     927                 : 
     928             252 :     for( iSBY = 0; iSBY < nSubBlocksPerColumn; iSBY++ )
     929                 :     {
     930             603 :         for( iSBX = 0; iSBX < nSubBlocksPerRow; iSBX++ )
     931                 :         {
     932             454 :             int nSubBlock = iSBX + iSBY * nSubBlocksPerRow;
     933                 :         
     934                 :             GDALRasterBlock **papoSubBlockGrid = 
     935             454 :                 (GDALRasterBlock **) papoBlocks[nSubBlock];
     936                 : 
     937             454 :             if( papoSubBlockGrid == NULL )
     938             361 :                 continue;
     939                 : 
     940            6045 :             for( int iY = 0; iY < SUBBLOCK_SIZE; iY++ )
     941                 :             {
     942          386880 :                 for( int iX = 0; iX < SUBBLOCK_SIZE; iX++ )
     943                 :                 {
     944          380928 :                     if( papoSubBlockGrid[iX + iY * SUBBLOCK_SIZE] != NULL )
     945                 :                     {
     946                 :                         CPLErr eErr;
     947                 : 
     948                 :                         eErr = FlushBlock( iX + iSBX * SUBBLOCK_SIZE, 
     949                 :                                            iY + iSBY * SUBBLOCK_SIZE,
     950           20872 :                                            eGlobalErr == CE_None );
     951           20872 :                         if( eErr != CE_None )
     952               0 :                             eGlobalErr = eErr;
     953                 :                     }
     954                 :                 }
     955                 :             }
     956                 : 
     957                 :             // We might as well get rid of this grid chunk since we know 
     958                 :             // it is now empty.
     959              93 :             papoBlocks[nSubBlock] = NULL;
     960              93 :             CPLFree( papoSubBlockGrid );
     961                 :         }
     962                 :     }
     963                 : 
     964             103 :     return( eGlobalErr );
     965                 : }
     966                 : 
     967                 : /************************************************************************/
     968                 : /*                        GDALFlushRasterCache()                        */
     969                 : /************************************************************************/
     970                 : 
     971                 : /**
     972                 :  * \brief Flush raster data cache.
     973                 :  *
     974                 :  * @see GDALRasterBand::FlushCache()
     975                 :  */
     976                 : 
     977               8 : CPLErr CPL_STDCALL GDALFlushRasterCache( GDALRasterBandH hBand )
     978                 : 
     979                 : {
     980               8 :     VALIDATE_POINTER1( hBand, "GDALFlushRasterCache", CE_Failure );
     981                 : 
     982               8 :     return ((GDALRasterBand *) hBand)->FlushCache();
     983                 : }
     984                 : 
     985                 : /************************************************************************/
     986                 : /*                             FlushBlock()                             */
     987                 : /*                                                                      */
     988                 : /*      Flush a block out of the block cache.  If it has been           */
     989                 : /*      modified write it to disk.  If no specific tile is              */
     990                 : /*      indicated, write the oldest tile.                               */
     991                 : /*                                                                      */
     992                 : /*      Protected method.                                               */
     993                 : /************************************************************************/
     994                 : 
     995          367941 : CPLErr GDALRasterBand::FlushBlock( int nXBlockOff, int nYBlockOff, int bWriteDirtyBlock )
     996                 : 
     997                 : {
     998                 :     int             nBlockIndex;
     999          367941 :     GDALRasterBlock *poBlock = NULL;
    1000                 : 
    1001          367941 :     if( !papoBlocks )
    1002               0 :         return CE_None;
    1003                 :     
    1004                 : /* -------------------------------------------------------------------- */
    1005                 : /*      Validate the request                                            */
    1006                 : /* -------------------------------------------------------------------- */
    1007          367941 :     if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
    1008                 :     {
    1009                 :         ReportError( CE_Failure, CPLE_IllegalArg,
    1010                 :                   "Illegal nBlockXOff value (%d) in "
    1011                 :                         "GDALRasterBand::FlushBlock()\n",
    1012               0 :                   nXBlockOff );
    1013                 : 
    1014               0 :         return( CE_Failure );
    1015                 :     }
    1016                 : 
    1017          367941 :     if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
    1018                 :     {
    1019                 :         ReportError( CE_Failure, CPLE_IllegalArg,
    1020                 :                   "Illegal nBlockYOff value (%d) in "
    1021                 :                         "GDALRasterBand::FlushBlock()\n",
    1022               0 :                   nYBlockOff );
    1023                 : 
    1024               0 :         return( CE_Failure );
    1025                 :     }
    1026                 : 
    1027                 : /* -------------------------------------------------------------------- */
    1028                 : /*      Simple case for single level caches.                            */
    1029                 : /* -------------------------------------------------------------------- */
    1030          367941 :     if( !bSubBlockingActive )
    1031                 :     {
    1032          347067 :         nBlockIndex = nXBlockOff + nYBlockOff * nBlocksPerRow;
    1033                 : 
    1034          347067 :         GDALRasterBlock::SafeLockBlock( papoBlocks + nBlockIndex );
    1035                 : 
    1036          347067 :         poBlock = papoBlocks[nBlockIndex];
    1037          347067 :         papoBlocks[nBlockIndex] = NULL;
    1038                 :     }
    1039                 : 
    1040                 : /* -------------------------------------------------------------------- */
    1041                 : /*      Identify our subblock.                                          */
    1042                 : /* -------------------------------------------------------------------- */
    1043                 :     else
    1044                 :     {
    1045                 :         int nSubBlock = TO_SUBBLOCK(nXBlockOff) 
    1046           20874 :             + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
    1047                 :         
    1048           20874 :         if( papoBlocks[nSubBlock] == NULL )
    1049               0 :             return CE_None;
    1050                 :         
    1051                 : /* -------------------------------------------------------------------- */
    1052                 : /*      Check within subblock.                                          */
    1053                 : /* -------------------------------------------------------------------- */
    1054                 :         GDALRasterBlock **papoSubBlockGrid = 
    1055           20874 :             (GDALRasterBlock **) papoBlocks[nSubBlock];
    1056                 :         
    1057                 :         int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
    1058           20874 :             + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
    1059                 :         
    1060           20874 :         GDALRasterBlock::SafeLockBlock( papoSubBlockGrid + nBlockInSubBlock );
    1061                 : 
    1062           20874 :         poBlock = papoSubBlockGrid[nBlockInSubBlock];
    1063           20874 :         papoSubBlockGrid[nBlockInSubBlock] = NULL;
    1064                 :     }
    1065                 : 
    1066                 : /* -------------------------------------------------------------------- */
    1067                 : /*      Is the target block dirty?  If so we need to write it.          */
    1068                 : /* -------------------------------------------------------------------- */
    1069          367941 :     CPLErr eErr = CE_None;
    1070                 : 
    1071          367941 :     if( poBlock == NULL )
    1072               0 :         return CE_None;
    1073                 : 
    1074          367941 :     poBlock->Detach();
    1075                 : 
    1076          367941 :     if( bWriteDirtyBlock && poBlock->GetDirty() )
    1077           53407 :         eErr = poBlock->Write();
    1078                 : 
    1079                 : /* -------------------------------------------------------------------- */
    1080                 : /*      Deallocate the block;                                           */
    1081                 : /* -------------------------------------------------------------------- */
    1082          367941 :     poBlock->DropLock();
    1083          367941 :     delete poBlock;
    1084                 : 
    1085          367941 :     return eErr;
    1086                 : }
    1087                 : 
    1088                 : /************************************************************************/
    1089                 : /*                        TryGetLockedBlockRef()                        */
    1090                 : /************************************************************************/
    1091                 : 
    1092                 : /**
    1093                 :  * \brief Try fetching block ref. 
    1094                 :  *
    1095                 :  * This method will returned the requested block (locked) if it is already
    1096                 :  * in the block cache for the layer.  If not, NULL is returned.  
    1097                 :  * 
    1098                 :  * If a non-NULL value is returned, then a lock for the block will have been
    1099                 :  * acquired on behalf of the caller.  It is absolutely imperative that the
    1100                 :  * caller release this lock (with GDALRasterBlock::DropLock()) or else
    1101                 :  * severe problems may result.
    1102                 :  *
    1103                 :  * @param nXBlockOff the horizontal block offset, with zero indicating
    1104                 :  * the left most block, 1 the next block and so forth. 
    1105                 :  *
    1106                 :  * @param nYBlockOff the vertical block offset, with zero indicating
    1107                 :  * the top most block, 1 the next block and so forth.
    1108                 :  * 
    1109                 :  * @return NULL if block not available, or locked block pointer. 
    1110                 :  */
    1111                 : 
    1112         4403607 : GDALRasterBlock *GDALRasterBand::TryGetLockedBlockRef( int nXBlockOff, 
    1113                 :                                                        int nYBlockOff )
    1114                 : 
    1115                 : {
    1116         4403607 :     int             nBlockIndex = 0;
    1117                 :     
    1118         4403607 :     if( !InitBlockInfo() )
    1119               0 :         return( NULL );
    1120                 :     
    1121                 : /* -------------------------------------------------------------------- */
    1122                 : /*      Validate the request                                            */
    1123                 : /* -------------------------------------------------------------------- */
    1124         4403607 :     if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
    1125                 :     {
    1126                 :         ReportError( CE_Failure, CPLE_IllegalArg,
    1127                 :                   "Illegal nBlockXOff value (%d) in "
    1128                 :                         "GDALRasterBand::TryGetLockedBlockRef()\n",
    1129               0 :                   nXBlockOff );
    1130                 : 
    1131               0 :         return( NULL );
    1132                 :     }
    1133                 : 
    1134         4403607 :     if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
    1135                 :     {
    1136                 :         ReportError( CE_Failure, CPLE_IllegalArg,
    1137                 :                   "Illegal nBlockYOff value (%d) in "
    1138                 :                         "GDALRasterBand::TryGetLockedBlockRef()\n",
    1139               0 :                   nYBlockOff );
    1140                 : 
    1141               0 :         return( NULL );
    1142                 :     }
    1143                 : 
    1144                 : /* -------------------------------------------------------------------- */
    1145                 : /*      Simple case for single level caches.                            */
    1146                 : /* -------------------------------------------------------------------- */
    1147         4403607 :     if( !bSubBlockingActive )
    1148                 :     {
    1149         2858299 :         nBlockIndex = nXBlockOff + nYBlockOff * nBlocksPerRow;
    1150                 :         
    1151         2858299 :         GDALRasterBlock::SafeLockBlock( papoBlocks + nBlockIndex );
    1152                 : 
    1153         2858299 :         return papoBlocks[nBlockIndex];
    1154                 :     }
    1155                 : 
    1156                 : /* -------------------------------------------------------------------- */
    1157                 : /*      Identify our subblock.                                          */
    1158                 : /* -------------------------------------------------------------------- */
    1159                 :     int nSubBlock = TO_SUBBLOCK(nXBlockOff) 
    1160         1545308 :         + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
    1161                 : 
    1162         1545308 :     if( papoBlocks[nSubBlock] == NULL )
    1163              93 :         return NULL;
    1164                 : 
    1165                 : /* -------------------------------------------------------------------- */
    1166                 : /*      Check within subblock.                                          */
    1167                 : /* -------------------------------------------------------------------- */
    1168                 :     GDALRasterBlock **papoSubBlockGrid = 
    1169         1545215 :         (GDALRasterBlock **) papoBlocks[nSubBlock];
    1170                 : 
    1171                 :     int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
    1172         1545215 :         + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
    1173                 : 
    1174         1545215 :     GDALRasterBlock::SafeLockBlock( papoSubBlockGrid + nBlockInSubBlock );
    1175                 : 
    1176         1545215 :     return papoSubBlockGrid[nBlockInSubBlock];
    1177                 : }
    1178                 : 
    1179                 : /************************************************************************/
    1180                 : /*                         GetLockedBlockRef()                          */
    1181                 : /************************************************************************/
    1182                 : 
    1183                 : /**
    1184                 :  * \brief Fetch a pointer to an internally cached raster block.
    1185                 :  *
    1186                 :  * This method will returned the requested block (locked) if it is already
    1187                 :  * in the block cache for the layer.  If not, the block will be read from 
    1188                 :  * the driver, and placed in the layer block cached, then returned.  If an
    1189                 :  * error occurs reading the block from the driver, a NULL value will be
    1190                 :  * returned.
    1191                 :  * 
    1192                 :  * If a non-NULL value is returned, then a lock for the block will have been
    1193                 :  * acquired on behalf of the caller.  It is absolutely imperative that the
    1194                 :  * caller release this lock (with GDALRasterBlock::DropLock()) or else
    1195                 :  * severe problems may result.
    1196                 :  *
    1197                 :  * Note that calling GetLockedBlockRef() on a previously uncached band will
    1198                 :  * enable caching.
    1199                 :  * 
    1200                 :  * @param nXBlockOff the horizontal block offset, with zero indicating
    1201                 :  * the left most block, 1 the next block and so forth. 
    1202                 :  *
    1203                 :  * @param nYBlockOff the vertical block offset, with zero indicating
    1204                 :  * the top most block, 1 the next block and so forth.
    1205                 :  * 
    1206                 :  * @param bJustInitialize If TRUE the block will be allocated and initialized,
    1207                 :  * but not actually read from the source.  This is useful when it will just
    1208                 :  * be completely set and written back. 
    1209                 :  *
    1210                 :  * @return pointer to the block object, or NULL on failure.
    1211                 :  */
    1212                 : 
    1213         4399108 : GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
    1214                 :                                                      int nYBlockOff,
    1215                 :                                                      int bJustInitialize )
    1216                 : 
    1217                 : {
    1218         4399108 :     GDALRasterBlock *poBlock = NULL;
    1219                 : 
    1220                 : /* -------------------------------------------------------------------- */
    1221                 : /*      Try and fetch from cache.                                       */
    1222                 : /* -------------------------------------------------------------------- */
    1223         4399108 :     poBlock = TryGetLockedBlockRef( nXBlockOff, nYBlockOff );
    1224                 : 
    1225                 : /* -------------------------------------------------------------------- */
    1226                 : /*      If we didn't find it in our memory cache, instantiate a         */
    1227                 : /*      block (potentially load from disk) and "adopt" it into the      */
    1228                 : /*      cache.                                                          */
    1229                 : /* -------------------------------------------------------------------- */
    1230         4399108 :     if( poBlock == NULL )
    1231                 :     {
    1232          367941 :         if( !InitBlockInfo() )
    1233               0 :             return( NULL );
    1234                 : 
    1235                 :     /* -------------------------------------------------------------------- */
    1236                 :     /*      Validate the request                                            */
    1237                 :     /* -------------------------------------------------------------------- */
    1238          367941 :         if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
    1239                 :         {
    1240                 :             ReportError( CE_Failure, CPLE_IllegalArg,
    1241                 :                       "Illegal nBlockXOff value (%d) in "
    1242                 :                       "GDALRasterBand::GetLockedBlockRef()\n",
    1243               0 :                       nXBlockOff );
    1244                 : 
    1245               0 :             return( NULL );
    1246                 :         }
    1247                 : 
    1248          367941 :         if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
    1249                 :         {
    1250                 :             ReportError( CE_Failure, CPLE_IllegalArg,
    1251                 :                       "Illegal nBlockYOff value (%d) in "
    1252                 :                       "GDALRasterBand::GetLockedBlockRef()\n",
    1253               0 :                       nYBlockOff );
    1254                 : 
    1255               0 :             return( NULL );
    1256                 :         }
    1257                 : 
    1258          367941 :         poBlock = new GDALRasterBlock( this, nXBlockOff, nYBlockOff );
    1259                 : 
    1260          367941 :         poBlock->AddLock();
    1261                 : 
    1262                 :         /* allocate data space */
    1263          367941 :         if( poBlock->Internalize() != CE_None )
    1264                 :         {
    1265               0 :             poBlock->DropLock();
    1266               0 :             delete poBlock;
    1267               0 :             return( NULL );
    1268                 :         }
    1269                 : 
    1270          367941 :         if ( AdoptBlock( nXBlockOff, nYBlockOff, poBlock ) != CE_None )
    1271                 :         {
    1272               0 :             poBlock->DropLock();
    1273               0 :             delete poBlock;
    1274               0 :             return( NULL );
    1275                 :         }
    1276                 : 
    1277          687294 :         if( !bJustInitialize
    1278          319353 :          && IReadBlock(nXBlockOff,nYBlockOff,poBlock->GetDataRef()) != CE_None)
    1279                 :         {
    1280              12 :             poBlock->DropLock();
    1281              12 :             FlushBlock( nXBlockOff, nYBlockOff );
    1282                 :             ReportError( CE_Failure, CPLE_AppDefined,
    1283                 :                 "IReadBlock failed at X offset %d, Y offset %d",
    1284              12 :                 nXBlockOff, nYBlockOff );
    1285              12 :             return( NULL );
    1286                 :         }
    1287                 : 
    1288          367929 :         if( !bJustInitialize )
    1289                 :         {
    1290          319341 :             nBlockReads++;
    1291          319341 :             if( nBlockReads == nBlocksPerRow * nBlocksPerColumn + 1 
    1292                 :                 && nBand == 1 && poDS != NULL )
    1293                 :             {
    1294                 :                 CPLDebug( "GDAL", "Potential thrashing on band %d of %s.",
    1295              75 :                           nBand, poDS->GetDescription() );
    1296                 :             }
    1297                 :         }
    1298                 :     }
    1299                 : 
    1300         4399096 :     return poBlock;
    1301                 : }
    1302                 : 
    1303                 : /************************************************************************/
    1304                 : /*                               Fill()                                 */
    1305                 : /************************************************************************/
    1306                 : 
    1307                 : /** 
    1308                 :  * \brief Fill this band with a constant value.
    1309                 :  *
    1310                 :  * GDAL makes no guarantees
    1311                 :  * about what values pixels in newly created files are set to, so this
    1312                 :  * method can be used to clear a band to a specified "default" value.
    1313                 :  * The fill value is passed in as a double but this will be converted
    1314                 :  * to the underlying type before writing to the file. An optional
    1315                 :  * second argument allows the imaginary component of a complex
    1316                 :  * constant value to be specified.
    1317                 :  * 
    1318                 :  * @param dfRealValue Real component of fill value
    1319                 :  * @param dfImaginaryValue Imaginary component of fill value, defaults to zero
    1320                 :  * 
    1321                 :  * @return CE_Failure if the write fails, otherwise CE_None
    1322                 :  */
    1323          168012 : CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
    1324                 : 
    1325                 :     // General approach is to construct a source block of the file's
    1326                 :     // native type containing the appropriate value and then copy this
    1327                 :     // to each block in the image via the RasterBlock cache. Using
    1328                 :     // the cache means we avoid file I/O if it's not necessary, at the
    1329                 :     // expense of some extra memcpy's (since we write to the
    1330                 :     // RasterBlock cache, which is then at some point written to the
    1331                 :     // underlying file, rather than simply directly to the underlying
    1332                 :     // file.)
    1333                 : 
    1334                 :     // Check we can write to the file
    1335          168012 :     if( eAccess == GA_ReadOnly ) {
    1336                 :         ReportError(CE_Failure, CPLE_NoWriteAccess,
    1337                 :                  "Attempt to write to read only dataset in"
    1338               0 :                  "GDALRasterBand::Fill().\n" );
    1339               0 :         return CE_Failure;
    1340                 :     }
    1341                 : 
    1342                 :     // Make sure block parameters are set
    1343          168012 :     if( !InitBlockInfo() )
    1344               0 :         return CE_Failure;
    1345                 : 
    1346                 :     // Allocate the source block
    1347          168012 :     int blockSize = nBlockXSize * nBlockYSize;
    1348          168012 :     int elementSize = GDALGetDataTypeSize(eDataType) / 8;
    1349          168012 :     int blockByteSize = blockSize * elementSize;
    1350          168012 :     unsigned char* srcBlock = (unsigned char*) VSIMalloc(blockByteSize);
    1351          168012 :     if (srcBlock == NULL) {
    1352                 :         ReportError(CE_Failure, CPLE_OutOfMemory,
    1353                 :                  "GDALRasterBand::Fill(): Out of memory "
    1354               0 :      "allocating %d bytes.\n", blockByteSize);
    1355               0 :         return CE_Failure;
    1356                 :     }
    1357                 :     
    1358                 :     // Initialize the first element of the block, doing type conversion
    1359          168012 :     double complexSrc[2] = { dfRealValue, dfImaginaryValue };
    1360          168012 :     GDALCopyWords(complexSrc, GDT_CFloat64, 0, srcBlock, eDataType, 0, 1);
    1361                 : 
    1362                 :     // Copy first element to the rest of the block
    1363        38898690 :     for (unsigned char* blockPtr = srcBlock + elementSize; 
    1364                 :    blockPtr < srcBlock + blockByteSize; blockPtr += elementSize) {
    1365        38730678 :   memcpy(blockPtr, srcBlock, elementSize);
    1366                 :     }
    1367                 : 
    1368                 :     // Write block to block cache
    1369          483374 :     for (int j = 0; j < nBlocksPerColumn; ++j) {
    1370          919724 :   for (int i = 0; i < nBlocksPerRow; ++i) {
    1371          604362 :       GDALRasterBlock* destBlock = GetLockedBlockRef(i, j, TRUE);
    1372          604362 :       if (destBlock == NULL) {
    1373                 :             ReportError(CE_Failure, CPLE_OutOfMemory,
    1374                 :        "GDALRasterBand::Fill(): Error "
    1375               0 :        "while retrieving cache block.\n");
    1376               0 :                 VSIFree(srcBlock);
    1377               0 :     return CE_Failure;
    1378                 :       }
    1379          604362 :             if (destBlock->GetDataRef() == NULL)
    1380                 :             {
    1381               0 :                 destBlock->DropLock();
    1382               0 :                 VSIFree(srcBlock);
    1383               0 :                 return CE_Failure;
    1384                 :             }
    1385          604362 :       memcpy(destBlock->GetDataRef(), srcBlock, blockByteSize);
    1386          604362 :       destBlock->MarkDirty();
    1387          604362 :             destBlock->DropLock();
    1388                 :   }
    1389                 :     }
    1390                 : 
    1391                 :     // Free up the source block
    1392          168012 :     VSIFree(srcBlock);
    1393                 : 
    1394          168012 :     return CE_None;
    1395                 : }
    1396                 : 
    1397                 : 
    1398                 : /************************************************************************/
    1399                 : /*                         GDALFillRaster()                             */
    1400                 : /************************************************************************/
    1401                 : 
    1402                 : /** 
    1403                 :  * \brief Fill this band with a constant value.
    1404                 :  *
    1405                 :  * @see GDALRasterBand::Fill()
    1406                 :  */
    1407          168012 : CPLErr CPL_STDCALL GDALFillRaster(GDALRasterBandH hBand, double dfRealValue, 
    1408                 :           double dfImaginaryValue)
    1409                 : {
    1410          168012 :     VALIDATE_POINTER1( hBand, "GDALFillRaster", CE_Failure );
    1411                 :     
    1412          168012 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1413          168012 :     return poBand->Fill(dfRealValue, dfImaginaryValue);
    1414                 : }
    1415                 : 
    1416                 : /************************************************************************/
    1417                 : /*                             GetAccess()                              */
    1418                 : /************************************************************************/
    1419                 : 
    1420                 : /**
    1421                 :  * \brief Find out if we have update permission for this band.
    1422                 :  *
    1423                 :  * This method is the same as the C function GDALGetRasterAccess().
    1424                 :  *
    1425                 :  * @return Either GA_Update or GA_ReadOnly.
    1426                 :  */
    1427                 : 
    1428             404 : GDALAccess GDALRasterBand::GetAccess()
    1429                 : 
    1430                 : {
    1431             404 :     return eAccess;
    1432                 : }
    1433                 : 
    1434                 : /************************************************************************/
    1435                 : /*                        GDALGetRasterAccess()                         */
    1436                 : /************************************************************************/
    1437                 : 
    1438                 : /**
    1439                 :  * \brief Find out if we have update permission for this band.
    1440                 :  *
    1441                 :  * @see GDALRasterBand::GetAccess()
    1442                 :  */
    1443                 : 
    1444             401 : GDALAccess CPL_STDCALL GDALGetRasterAccess( GDALRasterBandH hBand )
    1445                 : 
    1446                 : {
    1447             401 :     VALIDATE_POINTER1( hBand, "GDALGetRasterAccess", GA_ReadOnly );
    1448                 : 
    1449             401 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1450             401 :     return poBand->GetAccess();
    1451                 : }
    1452                 : 
    1453                 : /************************************************************************/
    1454                 : /*                          GetCategoryNames()                          */
    1455                 : /************************************************************************/
    1456                 : 
    1457                 : /**
    1458                 :  * \brief Fetch the list of category names for this raster.
    1459                 :  *
    1460                 :  * The return list is a "StringList" in the sense of the CPL functions.
    1461                 :  * That is a NULL terminated array of strings.  Raster values without 
    1462                 :  * associated names will have an empty string in the returned list.  The
    1463                 :  * first entry in the list is for raster values of zero, and so on. 
    1464                 :  *
    1465                 :  * The returned stringlist should not be altered or freed by the application.
    1466                 :  * It may change on the next GDAL call, so please copy it if it is needed
    1467                 :  * for any period of time. 
    1468                 :  * 
    1469                 :  * @return list of names, or NULL if none.
    1470                 :  */
    1471                 : 
    1472             105 : char **GDALRasterBand::GetCategoryNames()
    1473                 : 
    1474                 : {
    1475             105 :     return NULL;
    1476                 : }
    1477                 : 
    1478                 : /************************************************************************/
    1479                 : /*                     GDALGetRasterCategoryNames()                     */
    1480                 : /************************************************************************/
    1481                 : 
    1482                 : /**
    1483                 :  * \brief Fetch the list of category names for this raster.
    1484                 :  *
    1485                 :  * @see GDALRasterBand::GetCategoryNames()
    1486                 :  */
    1487                 : 
    1488              44 : char ** CPL_STDCALL GDALGetRasterCategoryNames( GDALRasterBandH hBand )
    1489                 : 
    1490                 : {
    1491              44 :     VALIDATE_POINTER1( hBand, "GDALGetRasterCategoryNames", NULL );
    1492                 : 
    1493              44 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1494              44 :     return poBand->GetCategoryNames();
    1495                 : }
    1496                 : 
    1497                 : /************************************************************************/
    1498                 : /*                          SetCategoryNames()                          */
    1499                 : /************************************************************************/
    1500                 : 
    1501                 : /**
    1502                 :  * \brief Set the category names for this band.
    1503                 :  *
    1504                 :  * See the GetCategoryNames() method for more on the interpretation of
    1505                 :  * category names. 
    1506                 :  *
    1507                 :  * This method is the same as the C function GDALSetRasterCategoryNames().
    1508                 :  *
    1509                 :  * @param papszNames the NULL terminated StringList of category names.  May
    1510                 :  * be NULL to just clear the existing list. 
    1511                 :  *
    1512                 :  * @return CE_None on success of CE_Failure on failure.  If unsupported
    1513                 :  * by the driver CE_Failure is returned, but no error message is reported.
    1514                 :  */
    1515                 : 
    1516               0 : CPLErr GDALRasterBand::SetCategoryNames( char ** papszNames )
    1517                 : 
    1518                 : {
    1519               0 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    1520                 :         ReportError( CE_Failure, CPLE_NotSupported,
    1521               0 :                   "SetCategoryNames() not supported for this dataset." );
    1522                 :     
    1523               0 :     return CE_Failure;
    1524                 : }
    1525                 : 
    1526                 : /************************************************************************/
    1527                 : /*                        GDALSetCategoryNames()                        */
    1528                 : /************************************************************************/
    1529                 : 
    1530                 : /**
    1531                 :  * \brief Set the category names for this band.
    1532                 :  *
    1533                 :  * @see GDALRasterBand::SetCategoryNames()
    1534                 :  */
    1535                 : 
    1536                 : CPLErr CPL_STDCALL 
    1537               1 : GDALSetRasterCategoryNames( GDALRasterBandH hBand, char ** papszNames )
    1538                 : 
    1539                 : {
    1540               1 :     VALIDATE_POINTER1( hBand, "GDALSetRasterCategoryNames", CE_Failure );
    1541                 : 
    1542               1 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1543               1 :     return poBand->SetCategoryNames( papszNames );
    1544                 : }
    1545                 : 
    1546                 : /************************************************************************/
    1547                 : /*                           GetNoDataValue()                           */
    1548                 : /************************************************************************/
    1549                 : 
    1550                 : /**
    1551                 :  * \brief Fetch the no data value for this band.
    1552                 :  * 
    1553                 :  * If there is no out of data value, an out of range value will generally
    1554                 :  * be returned.  The no data value for a band is generally a special marker
    1555                 :  * value used to mark pixels that are not valid data.  Such pixels should
    1556                 :  * generally not be displayed, nor contribute to analysis operations.
    1557                 :  *
    1558                 :  * This method is the same as the C function GDALGetRasterNoDataValue().
    1559                 :  *
    1560                 :  * @param pbSuccess pointer to a boolean to use to indicate if a value
    1561                 :  * is actually associated with this layer.  May be NULL (default).
    1562                 :  *
    1563                 :  * @return the nodata value for this band.
    1564                 :  */
    1565                 : 
    1566            4714 : double GDALRasterBand::GetNoDataValue( int *pbSuccess )
    1567                 : 
    1568                 : {
    1569            4714 :     if( pbSuccess != NULL )
    1570            4714 :         *pbSuccess = FALSE;
    1571                 :     
    1572            4714 :     return -1e10;
    1573                 : }
    1574                 : 
    1575                 : /************************************************************************/
    1576                 : /*                      GDALGetRasterNoDataValue()                      */
    1577                 : /************************************************************************/
    1578                 : 
    1579                 : /**
    1580                 :  * \brief Fetch the no data value for this band.
    1581                 :  * 
    1582                 :  * @see GDALRasterBand::GetNoDataValue()
    1583                 :  */
    1584                 : 
    1585                 : double CPL_STDCALL 
    1586             549 : GDALGetRasterNoDataValue( GDALRasterBandH hBand, int *pbSuccess )
    1587                 : 
    1588                 : {
    1589             549 :     VALIDATE_POINTER1( hBand, "GDALGetRasterNoDataValue", 0 );
    1590                 : 
    1591             549 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1592             549 :     return poBand->GetNoDataValue( pbSuccess );
    1593                 : }
    1594                 : 
    1595                 : /************************************************************************/
    1596                 : /*                           SetNoDataValue()                           */
    1597                 : /************************************************************************/
    1598                 : 
    1599                 : /**
    1600                 :  * \brief Set the no data value for this band. 
    1601                 :  *
    1602                 :  * To clear the nodata value, just set it with an "out of range" value.
    1603                 :  * Complex band no data values must have an imagery component of zero.
    1604                 :  *
    1605                 :  * This method is the same as the C function GDALSetRasterNoDataValue().
    1606                 :  *
    1607                 :  * @param dfNoData the value to set.
    1608                 :  *
    1609                 :  * @return CE_None on success, or CE_Failure on failure.  If unsupported
    1610                 :  * by the driver, CE_Failure is returned by no error message will have
    1611                 :  * been emitted.
    1612                 :  */
    1613                 : 
    1614               0 : CPLErr GDALRasterBand::SetNoDataValue( double dfNoData )
    1615                 : 
    1616                 : {
    1617               0 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    1618                 :         ReportError( CE_Failure, CPLE_NotSupported,
    1619               0 :                   "SetNoDataValue() not supported for this dataset." );
    1620                 : 
    1621               0 :     return CE_Failure;
    1622                 : }
    1623                 : 
    1624                 : /************************************************************************/
    1625                 : /*                         GDALSetRasterNoDataValue()                   */
    1626                 : /************************************************************************/
    1627                 : 
    1628                 : /**
    1629                 :  * \brief Set the no data value for this band. 
    1630                 :  *
    1631                 :  * @see GDALRasterBand::SetNoDataValue()
    1632                 :  */
    1633                 : 
    1634                 : CPLErr CPL_STDCALL 
    1635              65 : GDALSetRasterNoDataValue( GDALRasterBandH hBand, double dfValue )
    1636                 : 
    1637                 : {
    1638              65 :     VALIDATE_POINTER1( hBand, "GDALSetRasterNoDataValue", CE_Failure );
    1639                 : 
    1640              65 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1641              65 :     return poBand->SetNoDataValue( dfValue );
    1642                 : }
    1643                 : 
    1644                 : /************************************************************************/
    1645                 : /*                             GetMaximum()                             */
    1646                 : /************************************************************************/
    1647                 : 
    1648                 : /**
    1649                 :  * \brief Fetch the maximum value for this band.
    1650                 :  * 
    1651                 :  * For file formats that don't know this intrinsically, the maximum supported
    1652                 :  * value for the data type will generally be returned.  
    1653                 :  *
    1654                 :  * This method is the same as the C function GDALGetRasterMaximum().
    1655                 :  *
    1656                 :  * @param pbSuccess pointer to a boolean to use to indicate if the
    1657                 :  * returned value is a tight maximum or not.  May be NULL (default).
    1658                 :  *
    1659                 :  * @return the maximum raster value (excluding no data pixels)
    1660                 :  */
    1661                 : 
    1662             175 : double GDALRasterBand::GetMaximum( int *pbSuccess )
    1663                 : 
    1664                 : {
    1665             175 :     const char *pszValue = NULL;
    1666                 :     
    1667             175 :     if( (pszValue = GetMetadataItem("STATISTICS_MAXIMUM")) != NULL )
    1668                 :     {
    1669               3 :         if( pbSuccess != NULL )
    1670               3 :             *pbSuccess = TRUE;
    1671                 :         
    1672               3 :         return CPLAtofM(pszValue);
    1673                 :     }
    1674                 : 
    1675             172 :     if( pbSuccess != NULL )
    1676             145 :         *pbSuccess = FALSE;
    1677                 : 
    1678             172 :     switch( eDataType )
    1679                 :     {
    1680                 :       case GDT_Byte:
    1681                 :       {
    1682             129 :         const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
    1683             129 :         if (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"))
    1684               1 :             return 127;
    1685                 :         else
    1686             128 :             return 255;
    1687                 :       }
    1688                 : 
    1689                 :       case GDT_UInt16:
    1690               8 :         return 65535;
    1691                 : 
    1692                 :       case GDT_Int16:
    1693                 :       case GDT_CInt16:
    1694               8 :         return 32767;
    1695                 : 
    1696                 :       case GDT_Int32:
    1697                 :       case GDT_CInt32:
    1698               6 :         return 2147483647.0;
    1699                 : 
    1700                 :       case GDT_UInt32:
    1701               5 :         return 4294967295.0;
    1702                 : 
    1703                 :       case GDT_Float32:
    1704                 :       case GDT_CFloat32:
    1705               9 :         return 4294967295.0; /* not actually accurate */
    1706                 : 
    1707                 :       case GDT_Float64:
    1708                 :       case GDT_CFloat64:
    1709               7 :         return 4294967295.0; /* not actually accurate */
    1710                 : 
    1711                 :       default:
    1712               0 :         return 4294967295.0; /* not actually accurate */
    1713                 :     }
    1714                 : }
    1715                 : 
    1716                 : /************************************************************************/
    1717                 : /*                        GDALGetRasterMaximum()                        */
    1718                 : /************************************************************************/
    1719                 : 
    1720                 : /**
    1721                 :  * \brief Fetch the maximum value for this band.
    1722                 :  * 
    1723                 :  * @see GDALRasterBand::GetMaximum()
    1724                 :  */
    1725                 : 
    1726                 : double CPL_STDCALL 
    1727              49 : GDALGetRasterMaximum( GDALRasterBandH hBand, int *pbSuccess )
    1728                 : 
    1729                 : {
    1730              49 :     VALIDATE_POINTER1( hBand, "GDALGetRasterMaximum", 0 );
    1731                 : 
    1732              49 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1733              49 :     return poBand->GetMaximum( pbSuccess );
    1734                 : }
    1735                 : 
    1736                 : /************************************************************************/
    1737                 : /*                             GetMinimum()                             */
    1738                 : /************************************************************************/
    1739                 : 
    1740                 : /**
    1741                 :  * \brief Fetch the minimum value for this band.
    1742                 :  * 
    1743                 :  * For file formats that don't know this intrinsically, the minimum supported
    1744                 :  * value for the data type will generally be returned.  
    1745                 :  *
    1746                 :  * This method is the same as the C function GDALGetRasterMinimum().
    1747                 :  *
    1748                 :  * @param pbSuccess pointer to a boolean to use to indicate if the
    1749                 :  * returned value is a tight minimum or not.  May be NULL (default).
    1750                 :  *
    1751                 :  * @return the minimum raster value (excluding no data pixels)
    1752                 :  */
    1753                 : 
    1754             177 : double GDALRasterBand::GetMinimum( int *pbSuccess )
    1755                 : 
    1756                 : {
    1757             177 :     const char *pszValue = NULL;
    1758                 :     
    1759             177 :     if( (pszValue = GetMetadataItem("STATISTICS_MINIMUM")) != NULL )
    1760                 :     {
    1761               4 :         if( pbSuccess != NULL )
    1762               4 :             *pbSuccess = TRUE;
    1763                 :         
    1764               4 :         return CPLAtofM(pszValue);
    1765                 :     }
    1766                 : 
    1767             173 :     if( pbSuccess != NULL )
    1768             146 :         *pbSuccess = FALSE;
    1769                 : 
    1770             173 :     switch( eDataType )
    1771                 :     {
    1772                 :       case GDT_Byte:
    1773                 :       {
    1774             130 :         const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
    1775             130 :         if (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"))
    1776               1 :             return -128;
    1777                 :         else
    1778             129 :             return 0;
    1779                 :       }
    1780                 : 
    1781                 :       case GDT_UInt16:
    1782               8 :         return 0;
    1783                 : 
    1784                 :       case GDT_Int16:
    1785               7 :         return -32768;
    1786                 : 
    1787                 :       case GDT_Int32:
    1788               5 :         return -2147483648.0;
    1789                 : 
    1790                 :       case GDT_UInt32:
    1791               5 :         return 0;
    1792                 : 
    1793                 :       case GDT_Float32:
    1794               7 :         return -4294967295.0; /* not actually accurate */
    1795                 : 
    1796                 :       case GDT_Float64:
    1797               5 :         return -4294967295.0; /* not actually accurate */
    1798                 : 
    1799                 :       default:
    1800               6 :         return -4294967295.0; /* not actually accurate */
    1801                 :     }
    1802                 : }
    1803                 : 
    1804                 : /************************************************************************/
    1805                 : /*                        GDALGetRasterMinimum()                        */
    1806                 : /************************************************************************/
    1807                 : 
    1808                 : /**
    1809                 :  * \brief Fetch the minimum value for this band.
    1810                 :  * 
    1811                 :  * @see GDALRasterBand::GetMinimum()
    1812                 :  */
    1813                 : 
    1814                 : double CPL_STDCALL 
    1815              52 : GDALGetRasterMinimum( GDALRasterBandH hBand, int *pbSuccess )
    1816                 : 
    1817                 : {
    1818              52 :     VALIDATE_POINTER1( hBand, "GDALGetRasterMinimum", 0 );
    1819                 : 
    1820              52 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1821              52 :     return poBand->GetMinimum( pbSuccess );
    1822                 : }
    1823                 : 
    1824                 : /************************************************************************/
    1825                 : /*                       GetColorInterpretation()                       */
    1826                 : /************************************************************************/
    1827                 : 
    1828                 : /**
    1829                 :  * \brief How should this band be interpreted as color?
    1830                 :  *
    1831                 :  * GCI_Undefined is returned when the format doesn't know anything
    1832                 :  * about the color interpretation. 
    1833                 :  *
    1834                 :  * This method is the same as the C function 
    1835                 :  * GDALGetRasterColorInterpretation().
    1836                 :  *
    1837                 :  * @return color interpretation value for band.
    1838                 :  */
    1839                 : 
    1840              24 : GDALColorInterp GDALRasterBand::GetColorInterpretation()
    1841                 : 
    1842                 : {
    1843              24 :     return GCI_Undefined;
    1844                 : }
    1845                 : 
    1846                 : /************************************************************************/
    1847                 : /*                  GDALGetRasterColorInterpretation()                  */
    1848                 : /************************************************************************/
    1849                 : 
    1850                 : /**
    1851                 :  * \brief How should this band be interpreted as color?
    1852                 :  *
    1853                 :  * @see GDALRasterBand::GetColorInterpretation()
    1854                 :  */
    1855                 : 
    1856                 : GDALColorInterp CPL_STDCALL 
    1857             588 : GDALGetRasterColorInterpretation( GDALRasterBandH hBand )
    1858                 : 
    1859                 : {
    1860             588 :     VALIDATE_POINTER1( hBand, "GDALGetRasterColorInterpretation", GCI_Undefined );
    1861                 : 
    1862             588 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1863             588 :     return poBand->GetColorInterpretation();
    1864                 : }
    1865                 : 
    1866                 : /************************************************************************/
    1867                 : /*                       SetColorInterpretation()                       */
    1868                 : /************************************************************************/
    1869                 : 
    1870                 : /**
    1871                 :  * \brief Set color interpretation of a band.
    1872                 :  *
    1873                 :  * @param eColorInterp the new color interpretation to apply to this band.
    1874                 :  * 
    1875                 :  * @return CE_None on success or CE_Failure if method is unsupported by format.
    1876                 :  */
    1877                 : 
    1878               4 : CPLErr GDALRasterBand::SetColorInterpretation( GDALColorInterp eColorInterp)
    1879                 : 
    1880                 : {
    1881                 :     (void) eColorInterp;
    1882               4 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    1883                 :         ReportError( CE_Failure, CPLE_NotSupported,
    1884               1 :                   "SetColorInterpretation() not supported for this dataset." );
    1885               4 :     return CE_Failure;
    1886                 : }
    1887                 : 
    1888                 : /************************************************************************/
    1889                 : /*                  GDALSetRasterColorInterpretation()                  */
    1890                 : /************************************************************************/
    1891                 : 
    1892                 : /**
    1893                 :  * \brief Set color interpretation of a band.
    1894                 :  *
    1895                 :  * @see GDALRasterBand::SetColorInterpretation()
    1896                 :  */
    1897                 : 
    1898                 : CPLErr CPL_STDCALL 
    1899              92 : GDALSetRasterColorInterpretation( GDALRasterBandH hBand,
    1900                 :                                   GDALColorInterp eColorInterp )
    1901                 : 
    1902                 : {
    1903              92 :     VALIDATE_POINTER1( hBand, "GDALSetRasterColorInterpretation", CE_Failure );
    1904                 : 
    1905              92 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1906              92 :     return poBand->SetColorInterpretation(eColorInterp);
    1907                 : }
    1908                 : 
    1909                 : /************************************************************************/
    1910                 : /*                           GetColorTable()                            */
    1911                 : /************************************************************************/
    1912                 : 
    1913                 : /**
    1914                 :  * \brief Fetch the color table associated with band.
    1915                 :  *
    1916                 :  * If there is no associated color table, the return result is NULL.  The
    1917                 :  * returned color table remains owned by the GDALRasterBand, and can't
    1918                 :  * be depended on for long, nor should it ever be modified by the caller.
    1919                 :  *
    1920                 :  * This method is the same as the C function GDALGetRasterColorTable().
    1921                 :  *
    1922                 :  * @return internal color table, or NULL.
    1923                 :  */
    1924                 : 
    1925              31 : GDALColorTable *GDALRasterBand::GetColorTable()
    1926                 : 
    1927                 : {
    1928              31 :     return NULL;
    1929                 : }
    1930                 : 
    1931                 : /************************************************************************/
    1932                 : /*                      GDALGetRasterColorTable()                       */
    1933                 : /************************************************************************/
    1934                 : 
    1935                 : /**
    1936                 :  * \brief Fetch the color table associated with band.
    1937                 :  *
    1938                 :  * @see GDALRasterBand::GetColorTable()
    1939                 :  */
    1940                 : 
    1941             581 : GDALColorTableH CPL_STDCALL GDALGetRasterColorTable( GDALRasterBandH hBand )
    1942                 : 
    1943                 : {
    1944             581 :     VALIDATE_POINTER1( hBand, "GDALGetRasterColorTable", NULL );
    1945                 : 
    1946             581 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1947             581 :     return (GDALColorTableH)poBand->GetColorTable();
    1948                 : }
    1949                 : 
    1950                 : /************************************************************************/
    1951                 : /*                           SetColorTable()                            */
    1952                 : /************************************************************************/
    1953                 : 
    1954                 : /**
    1955                 :  * \brief Set the raster color table. 
    1956                 :  * 
    1957                 :  * The driver will make a copy of all desired data in the colortable.  It
    1958                 :  * remains owned by the caller after the call.
    1959                 :  *
    1960                 :  * This method is the same as the C function GDALSetRasterColorTable().
    1961                 :  *
    1962                 :  * @param poCT the color table to apply.  This may be NULL to clear the color 
    1963                 :  * table (where supported).
    1964                 :  *
    1965                 :  * @return CE_None on success, or CE_Failure on failure.  If the action is
    1966                 :  * unsupported by the driver, a value of CE_Failure is returned, but no
    1967                 :  * error is issued.
    1968                 :  */
    1969                 : 
    1970               0 : CPLErr GDALRasterBand::SetColorTable( GDALColorTable * poCT )
    1971                 : 
    1972                 : {
    1973                 :     (void) poCT;
    1974               0 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    1975                 :         ReportError( CE_Failure, CPLE_NotSupported,
    1976               0 :                   "SetColorTable() not supported for this dataset." );
    1977               0 :     return CE_Failure;
    1978                 : }
    1979                 : 
    1980                 : /************************************************************************/
    1981                 : /*                      GDALSetRasterColorTable()                       */
    1982                 : /************************************************************************/
    1983                 : 
    1984                 : /**
    1985                 :  * \brief Set the raster color table. 
    1986                 :  * 
    1987                 :  * @see GDALRasterBand::SetColorTable()
    1988                 :  */
    1989                 : 
    1990                 : CPLErr CPL_STDCALL 
    1991              22 : GDALSetRasterColorTable( GDALRasterBandH hBand, GDALColorTableH hCT )
    1992                 : 
    1993                 : {
    1994              22 :     VALIDATE_POINTER1( hBand, "GDALSetRasterColorTable", CE_Failure );
    1995                 : 
    1996              22 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1997              22 :     return poBand->SetColorTable( static_cast<GDALColorTable*>(hCT) );
    1998                 : }
    1999                 : 
    2000                 : /************************************************************************/
    2001                 : /*                       HasArbitraryOverviews()                        */
    2002                 : /************************************************************************/
    2003                 : 
    2004                 : /**
    2005                 :  * \brief Check for arbitrary overviews.
    2006                 :  *
    2007                 :  * This returns TRUE if the underlying datastore can compute arbitrary 
    2008                 :  * overviews efficiently, such as is the case with OGDI over a network. 
    2009                 :  * Datastores with arbitrary overviews don't generally have any fixed
    2010                 :  * overviews, but the RasterIO() method can be used in downsampling mode
    2011                 :  * to get overview data efficiently.
    2012                 :  *
    2013                 :  * This method is the same as the C function GDALHasArbitraryOverviews(),
    2014                 :  *
    2015                 :  * @return TRUE if arbitrary overviews available (efficiently), otherwise
    2016                 :  * FALSE. 
    2017                 :  */
    2018                 : 
    2019              48 : int GDALRasterBand::HasArbitraryOverviews()
    2020                 : 
    2021                 : {
    2022              48 :     return FALSE;
    2023                 : }
    2024                 : 
    2025                 : /************************************************************************/
    2026                 : /*                     GDALHasArbitraryOverviews()                      */
    2027                 : /************************************************************************/
    2028                 : 
    2029                 : /**
    2030                 :  * \brief Check for arbitrary overviews.
    2031                 :  *
    2032                 :  * @see GDALRasterBand::HasArbitraryOverviews()
    2033                 :  */
    2034                 : 
    2035              38 : int CPL_STDCALL GDALHasArbitraryOverviews( GDALRasterBandH hBand )
    2036                 : 
    2037                 : {
    2038              38 :     VALIDATE_POINTER1( hBand, "GDALHasArbitraryOverviews", 0 );
    2039                 :     
    2040              38 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2041              38 :     return poBand->HasArbitraryOverviews();
    2042                 : }
    2043                 : 
    2044                 : /************************************************************************/
    2045                 : /*                          GetOverviewCount()                          */
    2046                 : /************************************************************************/
    2047                 : 
    2048                 : /**
    2049                 :  * \brief Return the number of overview layers available.
    2050                 :  *
    2051                 :  * This method is the same as the C function GDALGetOverviewCount().
    2052                 :  *
    2053                 :  * @return overview count, zero if none.
    2054                 :  */
    2055                 : 
    2056          300215 : int GDALRasterBand::GetOverviewCount()
    2057                 : 
    2058                 : {
    2059          300215 :     if( poDS != NULL && poDS->oOvManager.IsInitialized() )
    2060          300095 :         return poDS->oOvManager.GetOverviewCount( nBand );
    2061                 :     else
    2062             120 :         return 0;
    2063                 : }
    2064                 : 
    2065                 : /************************************************************************/
    2066                 : /*                        GDALGetOverviewCount()                        */
    2067                 : /************************************************************************/
    2068                 : 
    2069                 : /**
    2070                 :  * \brief Return the number of overview layers available.
    2071                 :  *
    2072                 :  * @see GDALRasterBand::GetOverviewCount()
    2073                 :  */
    2074                 : 
    2075             112 : int CPL_STDCALL GDALGetOverviewCount( GDALRasterBandH hBand )
    2076                 : 
    2077                 : {
    2078             112 :     VALIDATE_POINTER1( hBand, "GDALGetOverviewCount", 0 );
    2079                 : 
    2080             112 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2081             112 :     return poBand->GetOverviewCount();
    2082                 : }
    2083                 : 
    2084                 : 
    2085                 : /************************************************************************/
    2086                 : /*                            GetOverview()                             */
    2087                 : /************************************************************************/
    2088                 : 
    2089                 : /**
    2090                 :  * \brief Fetch overview raster band object.
    2091                 :  *
    2092                 :  * This method is the same as the C function GDALGetOverview().
    2093                 :  * 
    2094                 :  * @param i overview index between 0 and GetOverviewCount()-1.
    2095                 :  * 
    2096                 :  * @return overview GDALRasterBand.
    2097                 :  */
    2098                 : 
    2099             356 : GDALRasterBand * GDALRasterBand::GetOverview( int i )
    2100                 : 
    2101                 : {
    2102             356 :     if( poDS != NULL && poDS->oOvManager.IsInitialized() )
    2103             356 :         return poDS->oOvManager.GetOverview( nBand, i );
    2104                 :     else
    2105               0 :         return NULL;
    2106                 : }
    2107                 : 
    2108                 : /************************************************************************/
    2109                 : /*                          GDALGetOverview()                           */
    2110                 : /************************************************************************/
    2111                 : 
    2112                 : /**
    2113                 :  * \brief Fetch overview raster band object.
    2114                 :  *
    2115                 :  * @see GDALRasterBand::GetOverview()
    2116                 :  */
    2117                 : 
    2118             251 : GDALRasterBandH CPL_STDCALL GDALGetOverview( GDALRasterBandH hBand, int i )
    2119                 : 
    2120                 : {
    2121             251 :     VALIDATE_POINTER1( hBand, "GDALGetOverview", NULL );
    2122                 : 
    2123             251 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2124             251 :     return (GDALRasterBandH) poBand->GetOverview(i);
    2125                 : }
    2126                 : 
    2127                 : /************************************************************************/
    2128                 : /*                      GetRasterSampleOverview()                       */
    2129                 : /************************************************************************/
    2130                 : 
    2131                 : /**
    2132                 :  * \brief Fetch best sampling overview.
    2133                 :  *
    2134                 :  * Returns the most reduced overview of the given band that still satisfies
    2135                 :  * the desired number of samples.  This function can be used with zero
    2136                 :  * as the number of desired samples to fetch the most reduced overview. 
    2137                 :  * The same band as was passed in will be returned if it has not overviews,
    2138                 :  * or if none of the overviews have enough samples.
    2139                 :  *
    2140                 :  * This method is the same as the C function GDALGetRasterSampleOverview().
    2141                 :  *
    2142                 :  * @param nDesiredSamples the returned band will have at least this many 
    2143                 :  * pixels.
    2144                 :  *
    2145                 :  * @return optimal overview or the band itself. 
    2146                 :  */
    2147                 : 
    2148               4 : GDALRasterBand *GDALRasterBand::GetRasterSampleOverview( int nDesiredSamples )
    2149                 : 
    2150                 : {
    2151               4 :     double dfBestSamples = 0; 
    2152               4 :     GDALRasterBand *poBestBand = this;
    2153                 : 
    2154               4 :     dfBestSamples = GetXSize() * (double)GetYSize();
    2155                 : 
    2156              22 :     for( int iOverview = 0; iOverview < GetOverviewCount(); iOverview++ )
    2157                 :     {
    2158              18 :         GDALRasterBand  *poOBand = GetOverview( iOverview );
    2159              18 :         double          dfOSamples = 0;
    2160                 : 
    2161              18 :         if (poOBand == NULL)
    2162               0 :             continue;
    2163                 : 
    2164              18 :         dfOSamples = poOBand->GetXSize() * (double)poOBand->GetYSize();
    2165                 : 
    2166              18 :         if( dfOSamples < dfBestSamples && dfOSamples > nDesiredSamples )
    2167                 :         {
    2168              12 :             dfBestSamples = dfOSamples;
    2169              12 :             poBestBand = poOBand;
    2170                 :         }
    2171                 :     }
    2172                 : 
    2173               4 :     return poBestBand;
    2174                 : }
    2175                 : 
    2176                 : /************************************************************************/
    2177                 : /*                    GDALGetRasterSampleOverview()                     */
    2178                 : /************************************************************************/
    2179                 : 
    2180                 : /**
    2181                 :  * \brief Fetch best sampling overview.
    2182                 :  *
    2183                 :  * @see GDALRasterBand::GetRasterSampleOverview()
    2184                 :  */
    2185                 : 
    2186                 : GDALRasterBandH CPL_STDCALL 
    2187               0 : GDALGetRasterSampleOverview( GDALRasterBandH hBand, int nDesiredSamples )
    2188                 : 
    2189                 : {
    2190               0 :     VALIDATE_POINTER1( hBand, "GDALGetRasterSampleOverview", NULL );
    2191                 : 
    2192               0 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2193                 :     return (GDALRasterBandH)
    2194               0 :         poBand->GetRasterSampleOverview( nDesiredSamples );
    2195                 : }
    2196                 : 
    2197                 : /************************************************************************/
    2198                 : /*                           BuildOverviews()                           */
    2199                 : /************************************************************************/
    2200                 : 
    2201                 : /**
    2202                 :  * \brief Build raster overview(s)
    2203                 :  *
    2204                 :  * If the operation is unsupported for the indicated dataset, then 
    2205                 :  * CE_Failure is returned, and CPLGetLastErrorNo() will return 
    2206                 :  * CPLE_NotSupported.
    2207                 :  *
    2208                 :  * WARNING:  It is not possible to build overviews for a single band in
    2209                 :  * TIFF format, and thus this method does not work for TIFF format, or any
    2210                 :  * formats that use the default overview building in TIFF format.  Instead
    2211                 :  * it is necessary to build overviews on the dataset as a whole using
    2212                 :  * GDALDataset::BuildOverviews().  That makes this method pretty useless
    2213                 :  * from a practical point of view. 
    2214                 :  *
    2215                 :  * @param pszResampling one of "NEAREST", "GAUSS", "CUBIC", "AVERAGE", "MODE",
    2216                 :  * "AVERAGE_MAGPHASE" or "NONE" controlling the downsampling method applied.
    2217                 :  * @param nOverviews number of overviews to build. 
    2218                 :  * @param panOverviewList the list of overview decimation factors to build. 
    2219                 :  * @param pfnProgress a function to call to report progress, or NULL.
    2220                 :  * @param pProgressData application data to pass to the progress function.
    2221                 :  *
    2222                 :  * @return CE_None on success or CE_Failure if the operation doesn't work. 
    2223                 :  */
    2224                 : 
    2225               0 : CPLErr GDALRasterBand::BuildOverviews( const char * pszResampling, 
    2226                 :                                        int nOverviews, 
    2227                 :                                        int * panOverviewList, 
    2228                 :                                        GDALProgressFunc pfnProgress, 
    2229                 :                                        void * pProgressData )
    2230                 : 
    2231                 : {
    2232                 :     (void) pszResampling;
    2233                 :     (void) nOverviews;
    2234                 :     (void) panOverviewList;
    2235                 :     (void) pfnProgress;
    2236                 :     (void) pProgressData;
    2237                 : 
    2238                 :     ReportError( CE_Failure, CPLE_NotSupported,
    2239               0 :               "BuildOverviews() not supported for this dataset." );
    2240                 :     
    2241               0 :     return( CE_Failure );
    2242                 : }
    2243                 : 
    2244                 : /************************************************************************/
    2245                 : /*                             GetOffset()                              */
    2246                 : /************************************************************************/
    2247                 : 
    2248                 : /**
    2249                 :  * \brief Fetch the raster value offset.
    2250                 :  *
    2251                 :  * This value (in combination with the GetScale() value) is used to
    2252                 :  * transform raw pixel values into the units returned by GetUnits().  
    2253                 :  * For example this might be used to store elevations in GUInt16 bands
    2254                 :  * with a precision of 0.1, and starting from -100. 
    2255                 :  * 
    2256                 :  * Units value = (raw value * scale) + offset
    2257                 :  * 
    2258                 :  * For file formats that don't know this intrinsically a value of zero
    2259                 :  * is returned. 
    2260                 :  *
    2261                 :  * This method is the same as the C function GDALGetRasterOffset().
    2262                 :  *
    2263                 :  * @param pbSuccess pointer to a boolean to use to indicate if the
    2264                 :  * returned value is meaningful or not.  May be NULL (default).
    2265                 :  *
    2266                 :  * @return the raster offset.
    2267                 :  */
    2268                 : 
    2269              47 : double GDALRasterBand::GetOffset( int *pbSuccess )
    2270                 : 
    2271                 : {
    2272              47 :     if( pbSuccess != NULL )
    2273              32 :         *pbSuccess = FALSE;
    2274                 : 
    2275              47 :     return 0.0;
    2276                 : }
    2277                 : 
    2278                 : /************************************************************************/
    2279                 : /*                        GDALGetRasterOffset()                         */
    2280                 : /************************************************************************/
    2281                 : 
    2282                 : /**
    2283                 :  * \brief Fetch the raster value offset.
    2284                 :  *
    2285                 :  * @see GDALRasterBand::GetOffset()
    2286                 :  */
    2287                 : 
    2288             125 : double CPL_STDCALL GDALGetRasterOffset( GDALRasterBandH hBand, int *pbSuccess )
    2289                 : 
    2290                 : {
    2291             125 :     VALIDATE_POINTER1( hBand, "GDALGetRasterOffset", 0 );
    2292                 : 
    2293             125 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2294             125 :     return poBand->GetOffset( pbSuccess );
    2295                 : }
    2296                 : 
    2297                 : /************************************************************************/
    2298                 : /*                             SetOffset()                              */
    2299                 : /************************************************************************/
    2300                 : 
    2301                 : /**
    2302                 :  * \brief Set scaling offset.
    2303                 :  *
    2304                 :  * Very few formats implement this method.   When not implemented it will
    2305                 :  * issue a CPLE_NotSupported error and return CE_Failure. 
    2306                 :  * 
    2307                 :  * @param dfNewOffset the new offset.
    2308                 :  *
    2309                 :  * @return CE_None or success or CE_Failure on failure. 
    2310                 :  */
    2311                 : 
    2312               0 : CPLErr GDALRasterBand::SetOffset( double dfNewOffset )
    2313                 : 
    2314                 : {
    2315               0 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    2316                 :         ReportError( CE_Failure, CPLE_NotSupported,
    2317               0 :                   "SetOffset() not supported on this raster band." );
    2318                 :     
    2319               0 :     return CE_Failure;
    2320                 : }
    2321                 : 
    2322                 : /************************************************************************/
    2323                 : /*                        GDALSetRasterOffset()                         */
    2324                 : /************************************************************************/
    2325                 : 
    2326                 : /**
    2327                 :  * \brief Set scaling offset.
    2328                 :  *
    2329                 :  * @see GDALRasterBand::SetOffset()
    2330                 :  */
    2331                 : 
    2332                 : CPLErr CPL_STDCALL 
    2333               5 : GDALSetRasterOffset( GDALRasterBandH hBand, double dfNewOffset )
    2334                 : 
    2335                 : {
    2336               5 :     VALIDATE_POINTER1( hBand, "GDALSetRasterOffset", CE_Failure );
    2337                 : 
    2338               5 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2339               5 :     return poBand->SetOffset( dfNewOffset );
    2340                 : }
    2341                 : 
    2342                 : /************************************************************************/
    2343                 : /*                              GetScale()                              */
    2344                 : /************************************************************************/
    2345                 : 
    2346                 : /**
    2347                 :  * \brief Fetch the raster value scale.
    2348                 :  *
    2349                 :  * This value (in combination with the GetOffset() value) is used to
    2350                 :  * transform raw pixel values into the units returned by GetUnits().  
    2351                 :  * For example this might be used to store elevations in GUInt16 bands
    2352                 :  * with a precision of 0.1, and starting from -100. 
    2353                 :  * 
    2354                 :  * Units value = (raw value * scale) + offset
    2355                 :  * 
    2356                 :  * For file formats that don't know this intrinsically a value of one
    2357                 :  * is returned. 
    2358                 :  *
    2359                 :  * This method is the same as the C function GDALGetRasterScale().
    2360                 :  *
    2361                 :  * @param pbSuccess pointer to a boolean to use to indicate if the
    2362                 :  * returned value is meaningful or not.  May be NULL (default).
    2363                 :  *
    2364                 :  * @return the raster scale.
    2365                 :  */
    2366                 : 
    2367              47 : double GDALRasterBand::GetScale( int *pbSuccess )
    2368                 : 
    2369                 : {
    2370              47 :     if( pbSuccess != NULL )
    2371              44 :         *pbSuccess = FALSE;
    2372                 : 
    2373              47 :     return 1.0;
    2374                 : }
    2375                 : 
    2376                 : /************************************************************************/
    2377                 : /*                         GDALGetRasterScale()                         */
    2378                 : /************************************************************************/
    2379                 : 
    2380                 : /**
    2381                 :  * \brief Fetch the raster value scale.
    2382                 :  *
    2383                 :  * @see GDALRasterBand::GetScale()
    2384                 :  */
    2385                 : 
    2386             125 : double CPL_STDCALL GDALGetRasterScale( GDALRasterBandH hBand, int *pbSuccess )
    2387                 : 
    2388                 : {
    2389             125 :     VALIDATE_POINTER1( hBand, "GDALGetRasterScale", 0 );
    2390                 : 
    2391             125 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2392             125 :     return poBand->GetScale( pbSuccess );
    2393                 : }
    2394                 : 
    2395                 : /************************************************************************/
    2396                 : /*                              SetScale()                              */
    2397                 : /************************************************************************/
    2398                 : 
    2399                 : /**
    2400                 :  * \brief Set scaling ratio.
    2401                 :  *
    2402                 :  * Very few formats implement this method.   When not implemented it will
    2403                 :  * issue a CPLE_NotSupported error and return CE_Failure. 
    2404                 :  * 
    2405                 :  * @param dfNewScale the new scale.
    2406                 :  *
    2407                 :  * @return CE_None or success or CE_Failure on failure. 
    2408                 :  */
    2409                 : 
    2410               0 : CPLErr GDALRasterBand::SetScale( double dfNewScale )
    2411                 : 
    2412                 : {
    2413               0 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    2414                 :         ReportError( CE_Failure, CPLE_NotSupported,
    2415               0 :                   "SetScale() not supported on this raster band." );
    2416                 :     
    2417               0 :     return CE_Failure;
    2418                 : }
    2419                 : 
    2420                 : /************************************************************************/
    2421                 : /*                        GDALSetRasterScale()                          */
    2422                 : /************************************************************************/
    2423                 : 
    2424                 : /**
    2425                 :  * \brief Set scaling ratio.
    2426                 :  *
    2427                 :  * @see GDALRasterBand::SetScale()
    2428                 :  */
    2429                 : 
    2430                 : CPLErr CPL_STDCALL 
    2431               5 : GDALSetRasterScale( GDALRasterBandH hBand, double dfNewOffset )
    2432                 : 
    2433                 : {
    2434               5 :     VALIDATE_POINTER1( hBand, "GDALSetRasterScale", CE_Failure );
    2435                 : 
    2436               5 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2437               5 :     return poBand->SetScale( dfNewOffset );
    2438                 : }
    2439                 : 
    2440                 : /************************************************************************/
    2441                 : /*                            GetUnitType()                             */
    2442                 : /************************************************************************/
    2443                 : 
    2444                 : /**
    2445                 :  * \brief Return raster unit type.
    2446                 :  *
    2447                 :  * Return a name for the units of this raster's values.  For instance, it
    2448                 :  * might be "m" for an elevation model in meters, or "ft" for feet.  If no 
    2449                 :  * units are available, a value of "" will be returned.  The returned string 
    2450                 :  * should not be modified, nor freed by the calling application.
    2451                 :  *
    2452                 :  * This method is the same as the C function GDALGetRasterUnitType(). 
    2453                 :  *
    2454                 :  * @return unit name string.
    2455                 :  */
    2456                 : 
    2457              24 : const char *GDALRasterBand::GetUnitType()
    2458                 : 
    2459                 : {
    2460              24 :     return "";
    2461                 : }
    2462                 : 
    2463                 : /************************************************************************/
    2464                 : /*                       GDALGetRasterUnitType()                        */
    2465                 : /************************************************************************/
    2466                 : 
    2467                 : /**
    2468                 :  * \brief Return raster unit type.
    2469                 :  *
    2470                 :  * @see GDALRasterBand::GetUnitType()
    2471                 :  */
    2472                 : 
    2473              48 : const char * CPL_STDCALL GDALGetRasterUnitType( GDALRasterBandH hBand )
    2474                 : 
    2475                 : {
    2476              48 :     VALIDATE_POINTER1( hBand, "GDALGetRasterUnitType", NULL );
    2477                 : 
    2478              48 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2479              48 :     return poBand->GetUnitType();
    2480                 : }
    2481                 : 
    2482                 : /************************************************************************/
    2483                 : /*                            SetUnitType()                             */
    2484                 : /************************************************************************/
    2485                 : 
    2486                 : /**
    2487                 :  * \brief Set unit type.
    2488                 :  *
    2489                 :  * Set the unit type for a raster band.  Values should be one of
    2490                 :  * "" (the default indicating it is unknown), "m" indicating meters, 
    2491                 :  * or "ft" indicating feet, though other nonstandard values are allowed.
    2492                 :  *
    2493                 :  * This method is the same as the C function GDALSetRasterUnitType(). 
    2494                 :  *
    2495                 :  * @param pszNewValue the new unit type value.
    2496                 :  *
    2497                 :  * @return CE_None on success or CE_Failure if not succuessful, or 
    2498                 :  * unsupported.
    2499                 :  */
    2500                 : 
    2501               0 : CPLErr GDALRasterBand::SetUnitType( const char *pszNewValue )
    2502                 : 
    2503                 : {
    2504               0 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    2505                 :         ReportError( CE_Failure, CPLE_NotSupported,
    2506               0 :                   "SetUnitType() not supported on this raster band." );
    2507               0 :     return CE_Failure;
    2508                 : }
    2509                 : 
    2510                 : /************************************************************************/
    2511                 : /*                       GDALSetRasterUnitType()                        */
    2512                 : /************************************************************************/
    2513                 : 
    2514                 : /**
    2515                 :  * \brief Set unit type.
    2516                 :  *
    2517                 :  * @see GDALRasterBand::SetUnitType()
    2518                 :  *
    2519                 :  * @since GDAL 1.8.0
    2520                 :  */
    2521                 : 
    2522               5 : CPLErr CPL_STDCALL GDALSetRasterUnitType( GDALRasterBandH hBand, const char *pszNewValue )
    2523                 : 
    2524                 : {
    2525               5 :     VALIDATE_POINTER1( hBand, "GDALSetRasterUnitType", CE_Failure );
    2526                 : 
    2527               5 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2528               5 :     return poBand->SetUnitType(pszNewValue);
    2529                 : }
    2530                 : 
    2531                 : /************************************************************************/
    2532                 : /*                              GetXSize()                              */
    2533                 : /************************************************************************/
    2534                 : 
    2535                 : /**
    2536                 :  * \brief Fetch XSize of raster. 
    2537                 :  *
    2538                 :  * This method is the same as the C function GDALGetRasterBandXSize(). 
    2539                 :  *
    2540                 :  * @return the width in pixels of this band.
    2541                 :  */
    2542                 : 
    2543          723567 : int GDALRasterBand::GetXSize()
    2544                 : 
    2545                 : {
    2546          723567 :     return nRasterXSize;
    2547                 : }
    2548                 : 
    2549                 : /************************************************************************/
    2550                 : /*                       GDALGetRasterBandXSize()                       */
    2551                 : /************************************************************************/
    2552                 : 
    2553                 : /**
    2554                 :  * \brief Fetch XSize of raster. 
    2555                 :  *
    2556                 :  * @see GDALRasterBand::GetXSize()
    2557                 :  */
    2558                 : 
    2559            2253 : int CPL_STDCALL GDALGetRasterBandXSize( GDALRasterBandH hBand )
    2560                 : 
    2561                 : {
    2562            2253 :     VALIDATE_POINTER1( hBand, "GDALGetRasterBandXSize", 0 );
    2563                 : 
    2564            2253 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2565            2253 :     return poBand->GetXSize();
    2566                 : }
    2567                 : 
    2568                 : /************************************************************************/
    2569                 : /*                              GetYSize()                              */
    2570                 : /************************************************************************/
    2571                 : 
    2572                 : /**
    2573                 :  * \brief Fetch YSize of raster. 
    2574                 :  *
    2575                 :  * This method is the same as the C function GDALGetRasterBandYSize(). 
    2576                 :  *
    2577                 :  * @return the height in pixels of this band.
    2578                 :  */
    2579                 : 
    2580          135180 : int GDALRasterBand::GetYSize()
    2581                 : 
    2582                 : {
    2583          135180 :     return nRasterYSize;
    2584                 : }
    2585                 : 
    2586                 : /************************************************************************/
    2587                 : /*                       GDALGetRasterBandYSize()                       */
    2588                 : /************************************************************************/
    2589                 : 
    2590                 : /**
    2591                 :  * \brief Fetch YSize of raster. 
    2592                 :  *
    2593                 :  * @see GDALRasterBand::GetYSize()
    2594                 :  */
    2595                 : 
    2596            2202 : int CPL_STDCALL GDALGetRasterBandYSize( GDALRasterBandH hBand )
    2597                 : 
    2598                 : {
    2599            2202 :     VALIDATE_POINTER1( hBand, "GDALGetRasterBandYSize", 0 );
    2600                 : 
    2601            2202 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2602            2202 :     return poBand->GetYSize();
    2603                 : }
    2604                 : 
    2605                 : /************************************************************************/
    2606                 : /*                              GetBand()                               */
    2607                 : /************************************************************************/
    2608                 : 
    2609                 : /**
    2610                 :  * \brief Fetch the band number.
    2611                 :  *
    2612                 :  * This method returns the band that this GDALRasterBand objects represents
    2613                 :  * within it's dataset.  This method may return a value of 0 to indicate
    2614                 :  * GDALRasterBand objects without an apparently relationship to a dataset,
    2615                 :  * such as GDALRasterBands serving as overviews.
    2616                 :  *
    2617                 :  * This method is the same as the C function GDALGetBandNumber().
    2618                 :  *
    2619                 :  * @return band number (1+) or 0 if the band number isn't known.
    2620                 :  */
    2621                 : 
    2622           16222 : int GDALRasterBand::GetBand()
    2623                 : 
    2624                 : {
    2625           16222 :     return nBand;
    2626                 : }
    2627                 : 
    2628                 : /************************************************************************/
    2629                 : /*                         GDALGetBandNumber()                          */
    2630                 : /************************************************************************/
    2631                 : 
    2632                 : /**
    2633                 :  * \brief Fetch the band number.
    2634                 :  *
    2635                 :  * @see GDALRasterBand::GetBand()
    2636                 :  */
    2637                 : 
    2638               6 : int CPL_STDCALL GDALGetBandNumber( GDALRasterBandH hBand )
    2639                 : 
    2640                 : {
    2641               6 :     VALIDATE_POINTER1( hBand, "GDALGetBandNumber", 0 );
    2642                 : 
    2643               6 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2644               6 :     return poBand->GetBand();
    2645                 : }
    2646                 : 
    2647                 : /************************************************************************/
    2648                 : /*                             GetDataset()                             */
    2649                 : /************************************************************************/
    2650                 : 
    2651                 : /**
    2652                 :  * \brief Fetch the owning dataset handle.
    2653                 :  *
    2654                 :  * Note that some GDALRasterBands are not considered to be a part of a dataset,
    2655                 :  * such as overviews or other "freestanding" bands. 
    2656                 :  *
    2657                 :  * This method is the same as the C function GDALGetBandDataset()
    2658                 :  *
    2659                 :  * @return the pointer to the GDALDataset to which this band belongs, or
    2660                 :  * NULL if this cannot be determined.
    2661                 :  */
    2662                 : 
    2663          497545 : GDALDataset *GDALRasterBand::GetDataset()
    2664                 : 
    2665                 : {
    2666          497545 :     return poDS;
    2667                 : }
    2668                 : 
    2669                 : /************************************************************************/
    2670                 : /*                         GDALGetBandDataset()                         */
    2671                 : /************************************************************************/
    2672                 : 
    2673                 : /**
    2674                 :  * \brief Fetch the owning dataset handle.
    2675                 :  *
    2676                 :  * @see GDALRasterBand::GetDataset()
    2677                 :  */
    2678                 : 
    2679              14 : GDALDatasetH CPL_STDCALL GDALGetBandDataset( GDALRasterBandH hBand )
    2680                 : 
    2681                 : {
    2682              14 :     VALIDATE_POINTER1( hBand, "GDALGetBandDataset", NULL );
    2683                 : 
    2684              14 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2685              14 :     return (GDALDatasetH) poBand->GetDataset();
    2686                 : }
    2687                 : 
    2688                 : /************************************************************************/
    2689                 : /*                            GetHistogram()                            */
    2690                 : /************************************************************************/
    2691                 : 
    2692                 : /**
    2693                 :  * \brief Compute raster histogram. 
    2694                 :  *
    2695                 :  * Note that the bucket size is (dfMax-dfMin) / nBuckets.  
    2696                 :  *
    2697                 :  * For example to compute a simple 256 entry histogram of eight bit data, 
    2698                 :  * the following would be suitable.  The unusual bounds are to ensure that
    2699                 :  * bucket boundaries don't fall right on integer values causing possible errors
    2700                 :  * due to rounding after scaling. 
    2701                 : <pre>
    2702                 :     int anHistogram[256];
    2703                 : 
    2704                 :     poBand->GetHistogram( -0.5, 255.5, 256, anHistogram, FALSE, FALSE, 
    2705                 :                           GDALDummyProgress, NULL );
    2706                 : </pre>
    2707                 :  *
    2708                 :  * Note that setting bApproxOK will generally result in a subsampling of the
    2709                 :  * file, and will utilize overviews if available.  It should generally 
    2710                 :  * produce a representative histogram for the data that is suitable for use
    2711                 :  * in generating histogram based luts for instance.  Generally bApproxOK is
    2712                 :  * much faster than an exactly computed histogram.
    2713                 :  *
    2714                 :  * @param dfMin the lower bound of the histogram.
    2715                 :  * @param dfMax the upper bound of the histogram.
    2716                 :  * @param nBuckets the number of buckets in panHistogram.
    2717                 :  * @param panHistogram array into which the histogram totals are placed.
    2718                 :  * @param bIncludeOutOfRange if TRUE values below the histogram range will
    2719                 :  * mapped into panHistogram[0], and values above will be mapped into 
    2720                 :  * panHistogram[nBuckets-1] otherwise out of range values are discarded.
    2721                 :  * @param bApproxOK TRUE if an approximate, or incomplete histogram OK.
    2722                 :  * @param pfnProgress function to report progress to completion. 
    2723                 :  * @param pProgressData application data to pass to pfnProgress. 
    2724                 :  *
    2725                 :  * @return CE_None on success, or CE_Failure if something goes wrong. 
    2726                 :  */
    2727                 : 
    2728               7 : CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax, 
    2729                 :                                      int nBuckets, int *panHistogram, 
    2730                 :                                      int bIncludeOutOfRange, int bApproxOK,
    2731                 :                                      GDALProgressFunc pfnProgress, 
    2732                 :                                      void *pProgressData )
    2733                 : 
    2734                 : {
    2735               7 :     CPLAssert( NULL != panHistogram );
    2736                 : 
    2737               7 :     if( pfnProgress == NULL )
    2738               4 :         pfnProgress = GDALDummyProgress;
    2739                 : 
    2740                 : /* -------------------------------------------------------------------- */
    2741                 : /*      If we have overviews, use them for the histogram.               */
    2742                 : /* -------------------------------------------------------------------- */
    2743               7 :     if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
    2744                 :     {
    2745                 :         // FIXME: should we use the most reduced overview here or use some
    2746                 :         // minimum number of samples like GDALRasterBand::ComputeStatistics()
    2747                 :         // does?
    2748               0 :         GDALRasterBand *poBestOverview = GetRasterSampleOverview( 0 );
    2749                 :         
    2750               0 :         if( poBestOverview != this )
    2751                 :         {
    2752                 :             return poBestOverview->GetHistogram( dfMin, dfMax, nBuckets,
    2753                 :                                                  panHistogram,
    2754                 :                                                  bIncludeOutOfRange, bApproxOK,
    2755               0 :                                                  pfnProgress, pProgressData );
    2756                 :         }
    2757                 :     }
    2758                 : 
    2759                 : /* -------------------------------------------------------------------- */
    2760                 : /*      Read actual data and build histogram.                           */
    2761                 : /* -------------------------------------------------------------------- */
    2762                 :     double      dfScale;
    2763                 : 
    2764               7 :     if( !pfnProgress( 0.0, "Compute Histogram", pProgressData ) )
    2765                 :     {
    2766               0 :         ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    2767               0 :         return CE_Failure;
    2768                 :     }
    2769                 : 
    2770               7 :     dfScale = nBuckets / (dfMax - dfMin);
    2771               7 :     memset( panHistogram, 0, sizeof(int) * nBuckets );
    2772                 : 
    2773               7 :     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
    2774               7 :     int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
    2775                 : 
    2776               7 :     if ( bApproxOK && HasArbitraryOverviews() )
    2777                 :     {
    2778                 : /* -------------------------------------------------------------------- */
    2779                 : /*      Figure out how much the image should be reduced to get an       */
    2780                 : /*      approximate value.                                              */
    2781                 : /* -------------------------------------------------------------------- */
    2782                 :         void    *pData;
    2783                 :         int     nXReduced, nYReduced;
    2784                 :         double  dfReduction = sqrt(
    2785               0 :             (double)nRasterXSize * nRasterYSize / GDALSTAT_APPROX_NUMSAMPLES );
    2786                 : 
    2787               0 :         if ( dfReduction > 1.0 )
    2788                 :         {
    2789               0 :             nXReduced = (int)( nRasterXSize / dfReduction );
    2790               0 :             nYReduced = (int)( nRasterYSize / dfReduction );
    2791                 : 
    2792                 :             // Catch the case of huge resizing ratios here
    2793               0 :             if ( nXReduced == 0 )
    2794               0 :                 nXReduced = 1;
    2795               0 :             if ( nYReduced == 0 )
    2796               0 :                 nYReduced = 1;
    2797                 :         }
    2798                 :         else
    2799                 :         {
    2800               0 :             nXReduced = nRasterXSize;
    2801               0 :             nYReduced = nRasterYSize;
    2802                 :         }
    2803                 : 
    2804                 :         pData =
    2805               0 :             CPLMalloc(GDALGetDataTypeSize(eDataType)/8 * nXReduced * nYReduced);
    2806                 : 
    2807                 :         CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
    2808               0 :                    nXReduced, nYReduced, eDataType, 0, 0 );
    2809               0 :         if ( eErr != CE_None )
    2810                 :         {
    2811               0 :             CPLFree(pData);
    2812               0 :             return eErr;
    2813                 :         }
    2814                 :         
    2815                 :         /* this isn't the fastest way to do this, but is easier for now */
    2816               0 :         for( int iY = 0; iY < nYReduced; iY++ )
    2817                 :         {
    2818               0 :             for( int iX = 0; iX < nXReduced; iX++ )
    2819                 :             {
    2820               0 :                 int    iOffset = iX + iY * nXReduced;
    2821                 :                 int    nIndex;
    2822               0 :                 double dfValue = 0.0;
    2823                 : 
    2824               0 :                 switch( eDataType )
    2825                 :                 {
    2826                 :                   case GDT_Byte:
    2827                 :                   {
    2828               0 :                     if (bSignedByte)
    2829               0 :                         dfValue = ((signed char *)pData)[iOffset];
    2830                 :                     else
    2831               0 :                         dfValue = ((GByte *)pData)[iOffset];
    2832               0 :                     break;
    2833                 :                   }
    2834                 :                   case GDT_UInt16:
    2835               0 :                     dfValue = ((GUInt16 *)pData)[iOffset];
    2836               0 :                     break;
    2837                 :                   case GDT_Int16:
    2838               0 :                     dfValue = ((GInt16 *)pData)[iOffset];
    2839               0 :                     break;
    2840                 :                   case GDT_UInt32:
    2841               0 :                     dfValue = ((GUInt32 *)pData)[iOffset];
    2842               0 :                     break;
    2843                 :                   case GDT_Int32:
    2844               0 :                     dfValue = ((GInt32 *)pData)[iOffset];
    2845               0 :                     break;
    2846                 :                   case GDT_Float32:
    2847               0 :                     dfValue = ((float *)pData)[iOffset];
    2848               0 :                     if (CPLIsNan(dfValue))
    2849               0 :                         continue;
    2850               0 :                     break;
    2851                 :                   case GDT_Float64:
    2852               0 :                     dfValue = ((double *)pData)[iOffset];
    2853               0 :                     if (CPLIsNan(dfValue))
    2854               0 :                         continue;
    2855               0 :                     break;
    2856                 :                   case GDT_CInt16:
    2857                 :                     {
    2858               0 :                         double dfReal = ((GInt16 *)pData)[iOffset*2];
    2859               0 :                         double dfImag = ((GInt16 *)pData)[iOffset*2+1];
    2860               0 :                         if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
    2861               0 :                             continue;
    2862               0 :                         dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    2863                 :                     }
    2864               0 :                     break;
    2865                 :                   case GDT_CInt32:
    2866                 :                     {
    2867               0 :                         double dfReal = ((GInt32 *)pData)[iOffset*2];
    2868               0 :                         double dfImag = ((GInt32 *)pData)[iOffset*2+1];
    2869               0 :                         if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
    2870               0 :                             continue;
    2871               0 :                         dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    2872                 :                     }
    2873               0 :                     break;
    2874                 :                   case GDT_CFloat32:
    2875                 :                     {
    2876               0 :                         double dfReal = ((float *)pData)[iOffset*2];
    2877               0 :                         double dfImag = ((float *)pData)[iOffset*2+1];
    2878               0 :                         if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
    2879               0 :                             continue;
    2880               0 :                         dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    2881                 :                     }
    2882               0 :                     break;
    2883                 :                   case GDT_CFloat64:
    2884                 :                     {
    2885               0 :                         double dfReal = ((double *)pData)[iOffset*2];
    2886               0 :                         double dfImag = ((double *)pData)[iOffset*2+1];
    2887               0 :                         if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
    2888               0 :                             continue;
    2889               0 :                         dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    2890                 :                     }
    2891               0 :                     break;
    2892                 :                   default:
    2893               0 :                     CPLAssert( FALSE );
    2894                 :                 }
    2895                 : 
    2896               0 :                 nIndex = (int) floor((dfValue - dfMin) * dfScale);
    2897                 :                 
    2898               0 :                 if( nIndex < 0 )
    2899                 :                 {
    2900               0 :                     if( bIncludeOutOfRange )
    2901               0 :                         panHistogram[0]++;
    2902                 :                 }
    2903               0 :                 else if( nIndex >= nBuckets )
    2904                 :                 {
    2905               0 :                     if( bIncludeOutOfRange )
    2906               0 :                         panHistogram[nBuckets-1]++;
    2907                 :                 }
    2908                 :                 else
    2909                 :                 {
    2910               0 :                     panHistogram[nIndex]++;
    2911                 :                 }
    2912                 :             }
    2913                 :         }
    2914                 : 
    2915               0 :         CPLFree( pData );
    2916                 :     }
    2917                 : 
    2918                 :     else    // No arbitrary overviews
    2919                 :     {
    2920                 :         int         nSampleRate;
    2921                 : 
    2922               7 :         if( !InitBlockInfo() )
    2923               0 :             return CE_Failure;
    2924                 :     
    2925                 : /* -------------------------------------------------------------------- */
    2926                 : /*      Figure out the ratio of blocks we will read to get an           */
    2927                 : /*      approximate value.                                              */
    2928                 : /* -------------------------------------------------------------------- */
    2929                 : 
    2930               7 :         if ( bApproxOK )
    2931                 :         {
    2932                 :             nSampleRate = 
    2933               2 :                 (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn));
    2934                 :         }
    2935                 :         else
    2936               5 :             nSampleRate = 1;
    2937                 :     
    2938                 : /* -------------------------------------------------------------------- */
    2939                 : /*      Read the blocks, and add to histogram.                          */
    2940                 : /* -------------------------------------------------------------------- */
    2941              26 :         for( int iSampleBlock = 0; 
    2942                 :              iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
    2943                 :              iSampleBlock += nSampleRate )
    2944                 :         {
    2945                 :             int  iXBlock, iYBlock, nXCheck, nYCheck;
    2946                 :             GDALRasterBlock *poBlock;
    2947                 :             void* pData;
    2948                 : 
    2949              19 :             if( !pfnProgress( iSampleBlock
    2950                 :                               / ((double)nBlocksPerRow * nBlocksPerColumn),
    2951                 :                               "Compute Histogram", pProgressData ) )
    2952               0 :                 return CE_Failure;
    2953                 : 
    2954              19 :             iYBlock = iSampleBlock / nBlocksPerRow;
    2955              19 :             iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
    2956                 :             
    2957              19 :             poBlock = GetLockedBlockRef( iXBlock, iYBlock );
    2958              19 :             if( poBlock == NULL )
    2959               0 :                 return CE_Failure;
    2960              19 :             if( poBlock->GetDataRef() == NULL )
    2961                 :             {
    2962               0 :                 poBlock->DropLock();
    2963               0 :                 return CE_Failure;
    2964                 :             }
    2965                 :             
    2966              19 :             pData = poBlock->GetDataRef();
    2967                 :             
    2968              19 :             if( (iXBlock+1) * nBlockXSize > GetXSize() )
    2969               0 :                 nXCheck = GetXSize() - iXBlock * nBlockXSize;
    2970                 :             else
    2971              19 :                 nXCheck = nBlockXSize;
    2972                 : 
    2973              19 :             if( (iYBlock+1) * nBlockYSize > GetYSize() )
    2974               2 :                 nYCheck = GetYSize() - iYBlock * nBlockYSize;
    2975                 :             else
    2976              17 :                 nYCheck = nBlockYSize;
    2977                 : 
    2978                 :             /* this is a special case for a common situation */
    2979              19 :             if( eDataType == GDT_Byte && !bSignedByte
    2980                 :                 && dfScale == 1.0 && (dfMin >= -0.5 && dfMin <= 0.5)
    2981                 :                 && nYCheck == nBlockYSize && nXCheck == nBlockXSize
    2982                 :                 && nBuckets == 256 )
    2983                 :             {
    2984               4 :                 int    nPixels = nXCheck * nYCheck;
    2985               4 :                 GByte  *pabyData = (GByte *) pData;
    2986                 :                 
    2987            9304 :                 for( int i = 0; i < nPixels; i++ )
    2988            9300 :                     panHistogram[pabyData[i]]++;
    2989                 : 
    2990               4 :                 poBlock->DropLock();
    2991               4 :                 continue; /* to next sample block */
    2992                 :             }
    2993                 : 
    2994                 :             /* this isn't the fastest way to do this, but is easier for now */
    2995             146 :             for( int iY = 0; iY < nYCheck; iY++ )
    2996                 :             {
    2997           12091 :                 for( int iX = 0; iX < nXCheck; iX++ )
    2998                 :                 {
    2999           11960 :                     int    iOffset = iX + iY * nBlockXSize;
    3000                 :                     int    nIndex;
    3001           11960 :                     double dfValue = 0.0;
    3002                 : 
    3003           11960 :                     switch( eDataType )
    3004                 :                     {
    3005                 :                       case GDT_Byte:
    3006                 :                       {
    3007           11900 :                         if (bSignedByte)
    3008               0 :                             dfValue = ((signed char *) pData)[iOffset];
    3009                 :                         else
    3010           11900 :                             dfValue = ((GByte *) pData)[iOffset];
    3011           11900 :                         break;
    3012                 :                       }
    3013                 :                       case GDT_UInt16:
    3014               0 :                         dfValue = ((GUInt16 *) pData)[iOffset];
    3015               0 :                         break;
    3016                 :                       case GDT_Int16:
    3017               0 :                         dfValue = ((GInt16 *) pData)[iOffset];
    3018               0 :                         break;
    3019                 :                       case GDT_UInt32:
    3020               0 :                         dfValue = ((GUInt32 *) pData)[iOffset];
    3021               0 :                         break;
    3022                 :                       case GDT_Int32:
    3023              60 :                         dfValue = ((GInt32 *) pData)[iOffset];
    3024              60 :                         break;
    3025                 :                       case GDT_Float32:
    3026               0 :                         dfValue = ((float *) pData)[iOffset];
    3027               0 :                         if (CPLIsNan(dfValue))
    3028               0 :                             continue;
    3029               0 :                         break;
    3030                 :                       case GDT_Float64:
    3031               0 :                         dfValue = ((double *) pData)[iOffset];
    3032               0 :                         if (CPLIsNan(dfValue))
    3033               0 :                             continue;
    3034               0 :                         break;
    3035                 :                       case GDT_CInt16:
    3036                 :                         {
    3037                 :                             double  dfReal =
    3038               0 :                                 ((GInt16 *) pData)[iOffset*2];
    3039                 :                             double  dfImag =
    3040               0 :                                 ((GInt16 *) pData)[iOffset*2+1];
    3041               0 :                             dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    3042                 :                         }
    3043               0 :                         break;
    3044                 :                       case GDT_CInt32:
    3045                 :                         {
    3046                 :                             double  dfReal =
    3047               0 :                                 ((GInt32 *) pData)[iOffset*2];
    3048                 :                             double  dfImag =
    3049               0 :                                 ((GInt32 *) pData)[iOffset*2+1];
    3050               0 :                             dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    3051                 :                         }
    3052               0 :                         break;
    3053                 :                       case GDT_CFloat32:
    3054                 :                         {
    3055                 :                             double  dfReal =
    3056               0 :                                 ((float *) pData)[iOffset*2];
    3057                 :                             double  dfImag =
    3058               0 :                                 ((float *) pData)[iOffset*2+1];
    3059               0 :                             if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
    3060               0 :                                 continue;
    3061               0 :                             dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    3062                 :                         }
    3063               0 :                         break;
    3064                 :                       case GDT_CFloat64:
    3065                 :                         {
    3066                 :                             double  dfReal =
    3067               0 :                                 ((double *) pData)[iOffset*2];
    3068                 :                             double  dfImag =
    3069               0 :                                 ((double *) pData)[iOffset*2+1];
    3070               0 :                             if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
    3071               0 :                                 continue;
    3072               0 :                             dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    3073                 :                         }
    3074               0 :                         break;
    3075                 :                       default:
    3076               0 :                         CPLAssert( FALSE );
    3077               0 :                         return CE_Failure;
    3078                 :                     }
    3079                 :                     
    3080           11960 :                     nIndex = (int) floor((dfValue - dfMin) * dfScale);
    3081                 : 
    3082           11960 :                     if( nIndex < 0 )
    3083                 :                     {
    3084               0 :                         if( bIncludeOutOfRange )
    3085               0 :                             panHistogram[0]++;
    3086                 :                     }
    3087           11960 :                     else if( nIndex >= nBuckets )
    3088                 :                     {
    3089               6 :                         if( bIncludeOutOfRange )
    3090               3 :                             panHistogram[nBuckets-1]++;
    3091                 :                     }
    3092                 :                     else
    3093                 :                     {
    3094           11954 :                         panHistogram[nIndex]++;
    3095                 :                     }
    3096                 :                 }
    3097                 :             }
    3098                 : 
    3099              15 :             poBlock->DropLock();
    3100                 :         }
    3101                 :     }
    3102                 : 
    3103               7 :     pfnProgress( 1.0, "Compute Histogram", pProgressData );
    3104                 : 
    3105               7 :     return CE_None;
    3106                 : }
    3107                 : 
    3108                 : /************************************************************************/
    3109                 : /*                       GDALGetRasterHistogram()                       */
    3110                 : /************************************************************************/
    3111                 : 
    3112                 : /**
    3113                 :  * \brief Compute raster histogram. 
    3114                 :  *
    3115                 :  * @see GDALRasterBand::GetHistogram()
    3116                 :  */
    3117                 : 
    3118                 : CPLErr CPL_STDCALL 
    3119               4 : GDALGetRasterHistogram( GDALRasterBandH hBand, 
    3120                 :                         double dfMin, double dfMax, 
    3121                 :                         int nBuckets, int *panHistogram, 
    3122                 :                         int bIncludeOutOfRange, int bApproxOK,
    3123                 :                         GDALProgressFunc pfnProgress, 
    3124                 :                         void *pProgressData )
    3125                 :     
    3126                 : {
    3127               4 :     VALIDATE_POINTER1( hBand, "GDALGetRasterHistogram", CE_Failure );
    3128               4 :     VALIDATE_POINTER1( panHistogram, "GDALGetRasterHistogram", CE_Failure );
    3129                 : 
    3130               4 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    3131                 : 
    3132                 :     return poBand->GetHistogram( dfMin, dfMax, nBuckets, panHistogram, 
    3133                 :                       bIncludeOutOfRange, bApproxOK,
    3134               4 :                       pfnProgress, pProgressData );
    3135                 : }
    3136                 : 
    3137                 : /************************************************************************/
    3138                 : /*                        GetDefaultHistogram()                         */
    3139                 : /************************************************************************/
    3140                 : 
    3141                 : /**
    3142                 :  * \brief Fetch default raster histogram. 
    3143                 :  *
    3144                 :  * The default method in GDALRasterBand will compute a default histogram. This
    3145                 :  * method is overriden by derived classes (such as GDALPamRasterBand, VRTDataset, HFADataset...)
    3146                 :  * that may be able to fetch efficiently an already stored histogram.
    3147                 :  *
    3148                 :  * @param pdfMin pointer to double value that will contain the lower bound of the histogram.
    3149                 :  * @param pdfMax pointer to double value that will contain the upper bound of the histogram.
    3150                 :  * @param pnBuckets pointer to int value that will contain the number of buckets in *ppanHistogram.
    3151                 :  * @param ppanHistogram pointer to array into which the histogram totals are placed. To be freed with VSIFree
    3152                 :  * @param bForce TRUE to force the computation. If FALSE and no default histogram is available, the method will return CE_Warning
    3153                 :  * @param pfnProgress function to report progress to completion. 
    3154                 :  * @param pProgressData application data to pass to pfnProgress. 
    3155                 :  *
    3156                 :  * @return CE_None on success, CE_Failure if something goes wrong, or 
    3157                 :  * CE_Warning if no default histogram is available.
    3158                 :  */
    3159                 : 
    3160                 : CPLErr 
    3161               6 :     GDALRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax, 
    3162                 :                                          int *pnBuckets, int **ppanHistogram, 
    3163                 :                                          int bForce,
    3164                 :                                          GDALProgressFunc pfnProgress, 
    3165                 :                                          void *pProgressData )
    3166                 : 
    3167                 : {
    3168               6 :     CPLAssert( NULL != pnBuckets );
    3169               6 :     CPLAssert( NULL != ppanHistogram );
    3170               6 :     CPLAssert( NULL != pdfMin );
    3171               6 :     CPLAssert( NULL != pdfMax );
    3172                 : 
    3173               6 :     *pnBuckets = 0;
    3174               6 :     *ppanHistogram = NULL;
    3175                 : 
    3176               6 :     if( !bForce )
    3177               3 :         return CE_Warning;
    3178                 : 
    3179               3 :     int nBuckets = 256;
    3180                 :     
    3181               3 :     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
    3182               3 :     int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
    3183                 : 
    3184               3 :     if( GetRasterDataType() == GDT_Byte && !bSignedByte)
    3185                 :     {
    3186               3 :         *pdfMin = -0.5;
    3187               3 :         *pdfMax = 255.5;
    3188                 :     }
    3189                 :     else
    3190                 :     {
    3191               0 :         CPLErr eErr = CE_Failure;
    3192               0 :         double dfHalfBucket = 0;
    3193                 : 
    3194               0 :         eErr = GetStatistics( TRUE, TRUE, pdfMin, pdfMax, NULL, NULL );
    3195               0 :         dfHalfBucket = (*pdfMax - *pdfMin) / (2 * nBuckets);
    3196               0 :         *pdfMin -= dfHalfBucket;
    3197               0 :         *pdfMax += dfHalfBucket;
    3198                 : 
    3199               0 :         if( eErr != CE_None )
    3200               0 :             return eErr;
    3201                 :     }
    3202                 : 
    3203               3 :     *ppanHistogram = (int *) VSICalloc(sizeof(int), nBuckets);
    3204               3 :     if( *ppanHistogram == NULL )
    3205                 :     {
    3206                 :         ReportError( CE_Failure, CPLE_OutOfMemory,
    3207               0 :                   "Out of memory in InitBlockInfo()." );
    3208               0 :         return CE_Failure;
    3209                 :     }
    3210                 : 
    3211               3 :     *pnBuckets = nBuckets;
    3212                 :     return GetHistogram( *pdfMin, *pdfMax, *pnBuckets, *ppanHistogram, 
    3213               3 :                          TRUE, FALSE, pfnProgress, pProgressData );
    3214                 : }
    3215                 : 
    3216                 : /************************************************************************/
    3217                 : /*                      GDALGetDefaultHistogram()                       */
    3218                 : /************************************************************************/
    3219                 : 
    3220                 : /**
    3221                 :   * \brief Fetch default raster histogram. 
    3222                 :   *
    3223                 :   * @see GDALRasterBand::GetDefaultHistogram()
    3224                 :   */
    3225                 : 
    3226               4 : CPLErr CPL_STDCALL GDALGetDefaultHistogram( GDALRasterBandH hBand, 
    3227                 :                                 double *pdfMin, double *pdfMax, 
    3228                 :                                 int *pnBuckets, int **ppanHistogram, 
    3229                 :                                 int bForce,
    3230                 :                                 GDALProgressFunc pfnProgress, 
    3231                 :                                 void *pProgressData )
    3232                 : 
    3233                 : {
    3234               4 :     VALIDATE_POINTER1( hBand, "GDALGetDefaultHistogram", CE_Failure );
    3235               4 :     VALIDATE_POINTER1( pdfMin, "GDALGetDefaultHistogram", CE_Failure );
    3236               4 :     VALIDATE_POINTER1( pdfMax, "GDALGetDefaultHistogram", CE_Failure );
    3237               4 :     VALIDATE_POINTER1( pnBuckets, "GDALGetDefaultHistogram", CE_Failure );
    3238               4 :     VALIDATE_POINTER1( ppanHistogram, "GDALGetDefaultHistogram", CE_Failure );
    3239                 : 
    3240               4 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    3241                 :     return poBand->GetDefaultHistogram( pdfMin, pdfMax,
    3242               4 :         pnBuckets, ppanHistogram, bForce, pfnProgress, pProgressData );
    3243                 : }
    3244                 : 
    3245                 : /************************************************************************/
    3246                 : /*                             AdviseRead()                             */
    3247                 : /************************************************************************/
    3248                 : 
    3249                 : /**
    3250                 :  * \brief Advise driver of upcoming read requests.
    3251                 :  *
    3252                 :  * Some GDAL drivers operate more efficiently if they know in advance what 
    3253                 :  * set of upcoming read requests will be made.  The AdviseRead() method allows
    3254                 :  * an application to notify the driver of the region of interest, 
    3255                 :  * and at what resolution the region will be read.  
    3256                 :  *
    3257                 :  * Many drivers just ignore the AdviseRead() call, but it can dramatically
    3258                 :  * accelerate access via some drivers.  
    3259                 :  *
    3260                 :  * @param nXOff The pixel offset to the top left corner of the region
    3261                 :  * of the band to be accessed.  This would be zero to start from the left side.
    3262                 :  *
    3263                 :  * @param nYOff The line offset to the top left corner of the region
    3264                 :  * of the band to be accessed.  This would be zero to start from the top.
    3265                 :  *
    3266                 :  * @param nXSize The width of the region of the band to be accessed in pixels.
    3267                 :  *
    3268                 :  * @param nYSize The height of the region of the band to be accessed in lines.
    3269                 :  *
    3270                 :  * @param nBufXSize the width of the buffer image into which the desired region
    3271                 :  * is to be read, or from which it is to be written.
    3272                 :  *
    3273                 :  * @param nBufYSize the height of the buffer image into which the desired
    3274                 :  * region is to be read, or from which it is to be written.
    3275                 :  *
    3276                 :  * @param eBufType the type of the pixel values in the pData data buffer.  The
    3277                 :  * pixel values will automatically be translated to/from the GDALRasterBand
    3278                 :  * data type as needed.
    3279                 :  *
    3280                 :  * @param papszOptions a list of name=value strings with special control 
    3281                 :  * options.  Normally this is NULL.
    3282                 :  *
    3283                 :  * @return CE_Failure if the request is invalid and CE_None if it works or
    3284                 :  * is ignored. 
    3285                 :  */
    3286                 : 
    3287               0 : CPLErr GDALRasterBand::AdviseRead( 
    3288                 :     int nXOff, int nYOff, int nXSize, int nYSize,
    3289                 :     int nBufXSize, int nBufYSize, GDALDataType eBufType, char **papszOptions )
    3290                 : 
    3291                 : {
    3292               0 :     return CE_None;
    3293                 : }
    3294                 : 
    3295                 : /************************************************************************/
    3296                 : /*                        GDALRasterAdviseRead()                        */
    3297                 : /************************************************************************/
    3298                 : 
    3299                 : 
    3300                 : /**
    3301                 :  * \brief Advise driver of upcoming read requests.
    3302                 :  *
    3303                 :  * @see GDALRasterBand::AdviseRead()
    3304                 :  */
    3305                 : 
    3306                 : CPLErr CPL_STDCALL 
    3307               0 : GDALRasterAdviseRead( GDALRasterBandH hBand, 
    3308                 :                       int nXOff, int nYOff, int nXSize, int nYSize,
    3309                 :                       int nBufXSize, int nBufYSize, 
    3310                 :                       GDALDataType eDT, char **papszOptions )
    3311                 :     
    3312                 : {
    3313               0 :     VALIDATE_POINTER1( hBand, "GDALRasterAdviseRead", CE_Failure );
    3314                 : 
    3315               0 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    3316                 :     return poBand->AdviseRead( nXOff, nYOff, nXSize, nYSize, 
    3317               0 :         nBufXSize, nBufYSize, eDT, papszOptions );
    3318                 : }
    3319                 : 
    3320                 : /************************************************************************/
    3321                 : /*                           GetStatistics()                            */
    3322                 : /************************************************************************/
    3323                 : 
    3324                 : /**
    3325                 :  * \brief Fetch image statistics. 
    3326                 :  *
    3327                 :  * Returns the minimum, maximum, mean and standard deviation of all
    3328                 :  * pixel values in this band.  If approximate statistics are sufficient,
    3329                 :  * the bApproxOK flag can be set to true in which case overviews, or a
    3330                 :  * subset of image tiles may be used in computing the statistics.  
    3331                 :  *
    3332                 :  * If bForce is FALSE results will only be returned if it can be done 
    3333                 :  * quickly (ie. without scanning the data).  If bForce is FALSE and 
    3334                 :  * results cannot be returned efficiently, the method will return CE_Warning
    3335                 :  * but no warning will have been issued.   This is a non-standard use of
    3336                 :  * the CE_Warning return value to indicate "nothing done". 
    3337                 :  *
    3338                 :  * Note that file formats using PAM (Persistent Auxilary Metadata) services
    3339                 :  * will generally cache statistics in the .pam file allowing fast fetch
    3340                 :  * after the first request. 
    3341                 :  *
    3342                 :  * This method is the same as the C function GDALGetRasterStatistics().
    3343                 :  *
    3344                 :  * @param bApproxOK If TRUE statistics may be computed based on overviews
    3345                 :  * or a subset of all tiles. 
    3346                 :  * 
    3347                 :  * @param bForce If FALSE statistics will only be returned if it can
    3348                 :  * be done without rescanning the image. 
    3349                 :  *
    3350                 :  * @param pdfMin Location into which to load image minimum (may be NULL).
    3351                 :  *
    3352                 :  * @param pdfMax Location into which to load image maximum (may be NULL).-
    3353                 :  *
    3354                 :  * @param pdfMean Location into which to load image mean (may be NULL).
    3355                 :  *
    3356                 :  * @param pdfStdDev Location into which to load image standard deviation 
    3357                 :  * (may be NULL).
    3358                 :  *
    3359                 :  * @return CE_None on success, CE_Warning if no values returned, 
    3360                 :  * CE_Failure if an error occurs.
    3361                 :  */
    3362                 : 
    3363             105 : CPLErr GDALRasterBand::GetStatistics( int bApproxOK, int bForce,
    3364                 :                                       double *pdfMin, double *pdfMax, 
    3365                 :                                       double *pdfMean, double *pdfStdDev )
    3366                 : 
    3367                 : {
    3368             105 :     double       dfMin=0.0, dfMax=0.0;
    3369                 : 
    3370                 : /* -------------------------------------------------------------------- */
    3371                 : /*      Do we already have metadata items for the requested values?     */
    3372                 : /* -------------------------------------------------------------------- */
    3373             153 :     if( (pdfMin == NULL || GetMetadataItem("STATISTICS_MINIMUM") != NULL)
    3374              16 :      && (pdfMax == NULL || GetMetadataItem("STATISTICS_MAXIMUM") != NULL)
    3375              16 :      && (pdfMean == NULL || GetMetadataItem("STATISTICS_MEAN") != NULL)
    3376              16 :      && (pdfStdDev == NULL || GetMetadataItem("STATISTICS_STDDEV") != NULL) )
    3377                 :     {
    3378              16 :         if( pdfMin != NULL )
    3379              16 :             *pdfMin = CPLAtofM(GetMetadataItem("STATISTICS_MINIMUM"));
    3380              16 :         if( pdfMax != NULL )
    3381              16 :             *pdfMax = CPLAtofM(GetMetadataItem("STATISTICS_MAXIMUM"));
    3382              16 :         if( pdfMean != NULL )
    3383              16 :             *pdfMean = CPLAtofM(GetMetadataItem("STATISTICS_MEAN"));
    3384              16 :         if( pdfStdDev != NULL )
    3385              16 :             *pdfStdDev = CPLAtofM(GetMetadataItem("STATISTICS_STDDEV"));
    3386                 : 
    3387              16 :         return CE_None;
    3388                 :     }
    3389                 : 
    3390                 : /* -------------------------------------------------------------------- */
    3391                 : /*      Does the driver already know the min/max?                       */
    3392                 : /* -------------------------------------------------------------------- */
    3393              89 :     if( bApproxOK && pdfMean == NULL && pdfStdDev == NULL )
    3394                 :     {
    3395                 :         int          bSuccessMin, bSuccessMax;
    3396                 : 
    3397               0 :         dfMin = GetMinimum( &bSuccessMin );
    3398               0 :         dfMax = GetMaximum( &bSuccessMax );
    3399                 : 
    3400               0 :         if( bSuccessMin && bSuccessMax )
    3401                 :         {
    3402               0 :             if( pdfMin != NULL )
    3403               0 :                 *pdfMin = dfMin;
    3404               0 :             if( pdfMax != NULL )
    3405               0 :                 *pdfMax = dfMax;
    3406               0 :             return CE_None;
    3407                 :         }
    3408                 :     }
    3409                 :     
    3410                 : /* -------------------------------------------------------------------- */
    3411                 : /*      Either return without results, or force computation.            */
    3412                 : /* -------------------------------------------------------------------- */
    3413              89 :     if( !bForce )
    3414              45 :         return CE_Warning;
    3415                 :     else
    3416                 :         return ComputeStatistics( bApproxOK, 
    3417                 :                                   pdfMin, pdfMax, pdfMean, pdfStdDev,
    3418              44 :                                   GDALDummyProgress, NULL );
    3419                 : }
    3420                 : 
    3421                 : /************************************************************************/
    3422                 : /*                      GDALGetRasterStatistics()                       */
    3423                 : /************************************************************************/
    3424                 : 
    3425                 : /**
    3426                 :  * \brief Fetch image statistics. 
    3427                 :  *
    3428                 :  * @see GDALRasterBand::GetStatistics()
    3429                 :  */
    3430                 : 
    3431              80 : CPLErr CPL_STDCALL GDALGetRasterStatistics( 
    3432                 :         GDALRasterBandH hBand, int bApproxOK, int bForce, 
    3433                 :         double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev )
    3434                 : 
    3435                 : {
    3436              80 :     VALIDATE_POINTER1( hBand, "GDALGetRasterStatistics", CE_Failure );
    3437                 : 
    3438              80 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    3439                 :     return poBand->GetStatistics( 
    3440              80 :         bApproxOK, bForce, pdfMin, pdfMax, pdfMean, pdfStdDev );
    3441                 : }
    3442                 : 
    3443                 : /************************************************************************/
    3444                 : /*                         ComputeStatistics()                          */
    3445                 : /************************************************************************/
    3446                 : 
    3447                 : /**
    3448                 :  * \brief Compute image statistics. 
    3449                 :  *
    3450                 :  * Returns the minimum, maximum, mean and standard deviation of all
    3451                 :  * pixel values in this band.  If approximate statistics are sufficient,
    3452                 :  * the bApproxOK flag can be set to true in which case overviews, or a
    3453                 :  * subset of image tiles may be used in computing the statistics.  
    3454                 :  *
    3455                 :  * Once computed, the statistics will generally be "set" back on the 
    3456                 :  * raster band using SetStatistics(). 
    3457                 :  *
    3458                 :  * This method is the same as the C function GDALComputeRasterStatistics().
    3459                 :  *
    3460                 :  * @param bApproxOK If TRUE statistics may be computed based on overviews
    3461                 :  * or a subset of all tiles. 
    3462                 :  * 
    3463                 :  * @param pdfMin Location into which to load image minimum (may be NULL).
    3464                 :  *
    3465                 :  * @param pdfMax Location into which to load image maximum (may be NULL).-
    3466                 :  *
    3467                 :  * @param pdfMean Location into which to load image mean (may be NULL).
    3468                 :  *
    3469                 :  * @param pdfStdDev Location into which to load image standard deviation 
    3470                 :  * (may be NULL).
    3471                 :  *
    3472                 :  * @param pfnProgress a function to call to report progress, or NULL.
    3473                 :  *
    3474                 :  * @param pProgressData application data to pass to the progress function.
    3475                 :  *
    3476                 :  * @return CE_None on success, or CE_Failure if an error occurs or processing
    3477                 :  * is terminated by the user.
    3478                 :  */
    3479                 : 
    3480                 : CPLErr 
    3481              54 : GDALRasterBand::ComputeStatistics( int bApproxOK,
    3482                 :                                    double *pdfMin, double *pdfMax, 
    3483                 :                                    double *pdfMean, double *pdfStdDev,
    3484                 :                                    GDALProgressFunc pfnProgress, 
    3485                 :                                    void *pProgressData )
    3486                 : 
    3487                 : {
    3488              54 :     if( pfnProgress == NULL )
    3489               4 :         pfnProgress = GDALDummyProgress;
    3490                 : 
    3491                 : /* -------------------------------------------------------------------- */
    3492                 : /*      If we have overview bands, use them for statistics.             */
    3493                 : /* -------------------------------------------------------------------- */
    3494              54 :     if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
    3495                 :     {
    3496                 :         GDALRasterBand *poBand;
    3497                 : 
    3498               4 :         poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
    3499                 : 
    3500               4 :         if( poBand != this )
    3501                 :             return poBand->ComputeStatistics( FALSE,  
    3502                 :                                               pdfMin, pdfMax, 
    3503                 :                                               pdfMean, pdfStdDev,
    3504               4 :                                               pfnProgress, pProgressData );
    3505                 :     }
    3506                 : 
    3507                 : /* -------------------------------------------------------------------- */
    3508                 : /*      Read actual data and compute statistics.                        */
    3509                 : /* -------------------------------------------------------------------- */
    3510              50 :     double      dfMin = 0.0, dfMax = 0.0;
    3511              50 :     int         bGotNoDataValue, bFirstValue = TRUE;
    3512              50 :     double      dfNoDataValue, dfSum = 0.0, dfSum2 = 0.0;
    3513              50 :     GIntBig     nSampleCount = 0;
    3514                 : 
    3515              50 :     if( !pfnProgress( 0.0, "Compute Statistics", pProgressData ) )
    3516                 :     {
    3517               0 :         ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3518               0 :         return CE_Failure;
    3519                 :     }
    3520                 : 
    3521              50 :     dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
    3522              50 :     bGotNoDataValue = bGotNoDataValue && !CPLIsNan(dfNoDataValue);
    3523                 : 
    3524              50 :     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
    3525              50 :     int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
    3526                 :     
    3527              50 :     if ( bApproxOK && HasArbitraryOverviews() )
    3528                 :     {
    3529                 : /* -------------------------------------------------------------------- */
    3530                 : /*      Figure out how much the image should be reduced to get an       */
    3531                 : /*      approximate value.                                              */
    3532                 : /* -------------------------------------------------------------------- */
    3533                 :         void    *pData;
    3534                 :         int     nXReduced, nYReduced;
    3535                 :         double  dfReduction = sqrt(
    3536               0 :             (double)nRasterXSize * nRasterYSize / GDALSTAT_APPROX_NUMSAMPLES );
    3537                 : 
    3538               0 :         if ( dfReduction > 1.0 )
    3539                 :         {
    3540               0 :             nXReduced = (int)( nRasterXSize / dfReduction );
    3541               0 :             nYReduced = (int)( nRasterYSize / dfReduction );
    3542                 : 
    3543                 :             // Catch the case of huge resizing ratios here
    3544               0 :             if ( nXReduced == 0 )
    3545               0 :                 nXReduced = 1;
    3546               0 :             if ( nYReduced == 0 )
    3547               0 :                 nYReduced = 1;
    3548                 :         }
    3549                 :         else
    3550                 :         {
    3551               0 :             nXReduced = nRasterXSize;
    3552               0 :             nYReduced = nRasterYSize;
    3553                 :         }
    3554                 : 
    3555                 :         pData =
    3556               0 :             CPLMalloc(GDALGetDataTypeSize(eDataType)/8 * nXReduced * nYReduced);
    3557                 : 
    3558                 :         CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
    3559               0 :                    nXReduced, nYReduced, eDataType, 0, 0 );
    3560               0 :         if ( eErr != CE_None )
    3561                 :         {
    3562               0 :             CPLFree(pData);
    3563               0 :             return eErr;
    3564                 :         }
    3565                 : 
    3566                 :         /* this isn't the fastest way to do this, but is easier for now */
    3567               0 :         for( int iY = 0; iY < nYReduced; iY++ )
    3568                 :         {
    3569               0 :             for( int iX = 0; iX < nXReduced; iX++ )
    3570                 :             {
    3571               0 :                 int    iOffset = iX + iY * nXReduced;
    3572               0 :                 double dfValue = 0.0;
    3573                 : 
    3574               0 :                 switch( eDataType )
    3575                 :                 {
    3576                 :                   case GDT_Byte:
    3577                 :                   {
    3578               0 :                     if (bSignedByte)
    3579               0 :                         dfValue = ((signed char *)pData)[iOffset];
    3580                 :                     else
    3581               0 :                         dfValue = ((GByte *)pData)[iOffset];
    3582               0 :                     break;
    3583                 :                   }
    3584                 :                   case GDT_UInt16:
    3585               0 :                     dfValue = ((GUInt16 *)pData)[iOffset];
    3586               0 :                     break;
    3587                 :                   case GDT_Int16:
    3588               0 :                     dfValue = ((GInt16 *)pData)[iOffset];
    3589               0 :                     break;
    3590                 :                   case GDT_UInt32:
    3591               0 :                     dfValue = ((GUInt32 *)pData)[iOffset];
    3592               0 :                     break;
    3593                 :                   case GDT_Int32:
    3594               0 :                     dfValue = ((GInt32 *)pData)[iOffset];
    3595               0 :                     break;
    3596                 :                   case GDT_Float32:
    3597               0 :                     dfValue = ((float *)pData)[iOffset];
    3598               0 :                     if (CPLIsNan(dfValue))
    3599               0 :                         continue;
    3600               0 :                     break;
    3601                 :                   case GDT_Float64:
    3602               0 :                     dfValue = ((double *)pData)[iOffset];
    3603               0 :                     if (CPLIsNan(dfValue))
    3604               0 :                         continue;
    3605               0 :                     break;
    3606                 :                   case GDT_CInt16:
    3607               0 :                     dfValue = ((GInt16 *)pData)[iOffset*2];
    3608               0 :                     break;
    3609                 :                   case GDT_CInt32:
    3610               0 :                     dfValue = ((GInt32 *)pData)[iOffset*2];
    3611               0 :                     break;
    3612                 :                   case GDT_CFloat32:
    3613               0 :                     dfValue = ((float *)pData)[iOffset*2];
    3614               0 :                     if( CPLIsNan(dfValue) )
    3615               0 :                         continue;
    3616               0 :                     break;
    3617                 :                   case GDT_CFloat64:
    3618               0 :                     dfValue = ((double *)pData)[iOffset*2];
    3619               0 :                     if( CPLIsNan(dfValue) )
    3620               0 :                         continue;
    3621               0 :                     break;
    3622                 :                   default:
    3623               0 :                     CPLAssert( FALSE );
    3624                 :                 }
    3625                 :                 
    3626               0 :                 if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
    3627               0 :                     continue;
    3628                 : 
    3629               0 :                 if( bFirstValue )
    3630                 :                 {
    3631               0 :                     dfMin = dfMax = dfValue;
    3632               0 :                     bFirstValue = FALSE;
    3633                 :                 }
    3634                 :                 else
    3635                 :                 {
    3636               0 :                     dfMin = MIN(dfMin,dfValue);
    3637               0 :                     dfMax = MAX(dfMax,dfValue);
    3638                 :                 }
    3639                 : 
    3640               0 :                 dfSum += dfValue;
    3641               0 :                 dfSum2 += dfValue * dfValue;
    3642                 : 
    3643               0 :                 nSampleCount++;
    3644                 :             }
    3645                 :         }
    3646                 : 
    3647               0 :         CPLFree( pData );
    3648                 :     }
    3649                 : 
    3650                 :     else    // No arbitrary overviews
    3651                 :     {
    3652                 :         int     nSampleRate;
    3653                 :         
    3654              50 :         if( !InitBlockInfo() )
    3655               0 :             return CE_Failure;
    3656                 : 
    3657                 : /* -------------------------------------------------------------------- */
    3658                 : /*      Figure out the ratio of blocks we will read to get an           */
    3659                 : /*      approximate value.                                              */
    3660                 : /* -------------------------------------------------------------------- */
    3661              50 :         if ( bApproxOK )
    3662                 :         {
    3663                 :             nSampleRate = 
    3664               4 :                 (int)MAX( 1, sqrt((double)nBlocksPerRow * nBlocksPerColumn) );
    3665                 :         }
    3666                 :         else
    3667              46 :             nSampleRate = 1;
    3668                 : 
    3669             510 :         for( int iSampleBlock = 0; 
    3670                 :              iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
    3671                 :              iSampleBlock += nSampleRate )
    3672                 :         {
    3673                 :             int  iXBlock, iYBlock, nXCheck, nYCheck;
    3674                 :             GDALRasterBlock *poBlock;
    3675                 :             void* pData;
    3676                 : 
    3677             460 :             iYBlock = iSampleBlock / nBlocksPerRow;
    3678             460 :             iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
    3679                 :             
    3680             460 :             poBlock = GetLockedBlockRef( iXBlock, iYBlock );
    3681             460 :             if( poBlock == NULL )
    3682               0 :                 continue;
    3683             460 :             if( poBlock->GetDataRef() == NULL )
    3684                 :             {
    3685               0 :                 poBlock->DropLock();
    3686               0 :                 continue;
    3687                 :             }
    3688                 :             
    3689             460 :             pData = poBlock->GetDataRef();
    3690                 :             
    3691             460 :             if( (iXBlock+1) * nBlockXSize > GetXSize() )
    3692               4 :                 nXCheck = GetXSize() - iXBlock * nBlockXSize;
    3693                 :             else
    3694             456 :                 nXCheck = nBlockXSize;
    3695                 : 
    3696             460 :             if( (iYBlock+1) * nBlockYSize > GetYSize() )
    3697               6 :                 nYCheck = GetYSize() - iYBlock * nBlockYSize;
    3698                 :             else
    3699             454 :                 nYCheck = nBlockYSize;
    3700                 : 
    3701                 :             /* this isn't the fastest way to do this, but is easier for now */
    3702            8966 :             for( int iY = 0; iY < nYCheck; iY++ )
    3703                 :             {
    3704         6908353 :                 for( int iX = 0; iX < nXCheck; iX++ )
    3705                 :                 {
    3706         6899847 :                     int    iOffset = iX + iY * nBlockXSize;
    3707         6899847 :                     double dfValue = 0.0;
    3708                 : 
    3709         6899847 :                     switch( eDataType )
    3710                 :                     {
    3711                 :                       case GDT_Byte:
    3712                 :                       {
    3713          585794 :                         if (bSignedByte)
    3714               5 :                             dfValue = ((signed char *)pData)[iOffset];
    3715                 :                         else
    3716          585789 :                             dfValue = ((GByte *)pData)[iOffset];
    3717          585794 :                         break;
    3718                 :                       }
    3719                 :                       case GDT_UInt16:
    3720         6312940 :                         dfValue = ((GUInt16 *)pData)[iOffset];
    3721         6312940 :                         break;
    3722                 :                       case GDT_Int16:
    3723             100 :                         dfValue = ((GInt16 *)pData)[iOffset];
    3724             100 :                         break;
    3725                 :                       case GDT_UInt32:
    3726             100 :                         dfValue = ((GUInt32 *)pData)[iOffset];
    3727             100 :                         break;
    3728                 :                       case GDT_Int32:
    3729             100 :                         dfValue = ((GInt32 *)pData)[iOffset];
    3730             100 :                         break;
    3731                 :                       case GDT_Float32:
    3732             213 :                         dfValue = ((float *)pData)[iOffset];
    3733             213 :                         if (CPLIsNan(dfValue))
    3734              10 :                             continue;
    3735             203 :                         break;
    3736                 :                       case GDT_Float64:
    3737             600 :                         dfValue = ((double *)pData)[iOffset];
    3738             600 :                         if (CPLIsNan(dfValue))
    3739              50 :                             continue;
    3740             550 :                         break;
    3741                 :                       case GDT_CInt16:
    3742               0 :                         dfValue = ((GInt16 *)pData)[iOffset*2];
    3743               0 :                         break;
    3744                 :                       case GDT_CInt32:
    3745               0 :                         dfValue = ((GInt32 *)pData)[iOffset*2];
    3746               0 :                         break;
    3747                 :                       case GDT_CFloat32:
    3748               0 :                         dfValue = ((float *)pData)[iOffset*2];
    3749               0 :                         if( CPLIsNan(dfValue) )
    3750               0 :                             continue;
    3751               0 :                         break;
    3752                 :                       case GDT_CFloat64:
    3753               0 :                         dfValue = ((double *)pData)[iOffset*2];
    3754               0 :                         if( CPLIsNan(dfValue) )
    3755               0 :                             continue;
    3756               0 :                         break;
    3757                 :                       default:
    3758               0 :                         CPLAssert( FALSE );
    3759                 :                     }
    3760                 : 
    3761         6899787 :                     if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
    3762              32 :                         continue;
    3763                 : 
    3764         6899755 :                     if( bFirstValue )
    3765                 :                     {
    3766              50 :                         dfMin = dfMax = dfValue;
    3767              50 :                         bFirstValue = FALSE;
    3768                 :                     }
    3769                 :                     else
    3770                 :                     {
    3771         6899705 :                         dfMin = MIN(dfMin,dfValue);
    3772         6899705 :                         dfMax = MAX(dfMax,dfValue);
    3773                 :                     }
    3774                 : 
    3775         6899755 :                     dfSum += dfValue;
    3776         6899755 :                     dfSum2 += dfValue * dfValue;
    3777                 : 
    3778         6899755 :                     nSampleCount++;
    3779                 :                 }
    3780                 :             }
    3781                 : 
    3782             460 :             poBlock->DropLock();
    3783                 : 
    3784             460 :             if ( !pfnProgress(iSampleBlock
    3785                 :                               / ((double)(nBlocksPerRow*nBlocksPerColumn)),
    3786                 :                               "Compute Statistics", pProgressData) )
    3787                 :             {
    3788               0 :                 ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3789               0 :                 return CE_Failure;
    3790                 :             }
    3791                 :         }
    3792                 :     }
    3793                 : 
    3794              50 :     if( !pfnProgress( 1.0, "Compute Statistics", pProgressData ) )
    3795                 :     {
    3796               0 :         ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3797               0 :         return CE_Failure;
    3798                 :     }
    3799                 : 
    3800                 : /* -------------------------------------------------------------------- */
    3801                 : /*      Save computed information.                                      */
    3802                 : /* -------------------------------------------------------------------- */
    3803              50 :     double dfMean = dfSum / nSampleCount;
    3804              50 :     double dfStdDev = sqrt((dfSum2 / nSampleCount) - (dfMean * dfMean));
    3805                 : 
    3806              50 :     if( nSampleCount > 0 )
    3807              50 :         SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
    3808                 : 
    3809                 : /* -------------------------------------------------------------------- */
    3810                 : /*      Record results.                                                 */
    3811                 : /* -------------------------------------------------------------------- */
    3812              50 :     if( pdfMin != NULL )
    3813              50 :         *pdfMin = dfMin;
    3814              50 :     if( pdfMax != NULL )
    3815              50 :         *pdfMax = dfMax;
    3816                 : 
    3817              50 :     if( pdfMean != NULL )
    3818              50 :         *pdfMean = dfMean;
    3819                 : 
    3820              50 :     if( pdfStdDev != NULL )
    3821              50 :         *pdfStdDev = dfStdDev;
    3822                 : 
    3823              50 :     if( nSampleCount > 0 )
    3824              50 :         return CE_None;
    3825                 :     else
    3826                 :     {
    3827                 :         ReportError( CE_Failure, CPLE_AppDefined,
    3828               0 :         "Failed to compute statistics, no valid pixels found in sampling." );
    3829               0 :         return CE_Failure;
    3830                 :     }
    3831                 : }
    3832                 : 
    3833                 : /************************************************************************/
    3834                 : /*                    GDALComputeRasterStatistics()                     */
    3835                 : /************************************************************************/
    3836                 : 
    3837                 : /**
    3838                 :   * \brief Compute image statistics. 
    3839                 :   *
    3840                 :   * @see GDALRasterBand::ComputeStatistics()
    3841                 :   */
    3842                 : 
    3843               4 : CPLErr CPL_STDCALL GDALComputeRasterStatistics( 
    3844                 :         GDALRasterBandH hBand, int bApproxOK, 
    3845                 :         double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev,
    3846                 :         GDALProgressFunc pfnProgress, void *pProgressData )
    3847                 : 
    3848                 : {
    3849               4 :     VALIDATE_POINTER1( hBand, "GDALComputeRasterStatistics", CE_Failure );
    3850                 : 
    3851               4 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    3852                 : 
    3853                 :     return poBand->ComputeStatistics( 
    3854                 :         bApproxOK, pdfMin, pdfMax, pdfMean, pdfStdDev,
    3855               4 :         pfnProgress, pProgressData );
    3856                 : }
    3857                 : 
    3858                 : /************************************************************************/
    3859                 : /*                           SetStatistics()                            */
    3860                 : /************************************************************************/
    3861                 : 
    3862                 : /**
    3863                 :  * \brief Set statistics on band.
    3864                 :  *
    3865                 :  * This method can be used to store min/max/mean/standard deviation
    3866                 :  * statistics on a raster band.  
    3867                 :  *
    3868                 :  * The default implementation stores them as metadata, and will only work 
    3869                 :  * on formats that can save arbitrary metadata.  This method cannot detect
    3870                 :  * whether metadata will be properly saved and so may return CE_None even
    3871                 :  * if the statistics will never be saved.
    3872                 :  *
    3873                 :  * This method is the same as the C function GDALSetRasterStatistics().
    3874                 :  * 
    3875                 :  * @param dfMin minimum pixel value.
    3876                 :  * 
    3877                 :  * @param dfMax maximum pixel value.
    3878                 :  *
    3879                 :  * @param dfMean mean (average) of all pixel values.    
    3880                 :  *
    3881                 :  * @param dfStdDev Standard deviation of all pixel values.
    3882                 :  *
    3883                 :  * @return CE_None on success or CE_Failure on failure. 
    3884                 :  */
    3885                 : 
    3886              93 : CPLErr GDALRasterBand::SetStatistics( double dfMin, double dfMax, 
    3887                 :                                       double dfMean, double dfStdDev )
    3888                 : 
    3889                 : {
    3890              93 :     char szValue[128] = { 0 };
    3891                 : 
    3892              93 :     sprintf( szValue, "%.14g", dfMin );
    3893              93 :     SetMetadataItem( "STATISTICS_MINIMUM", szValue );
    3894                 : 
    3895              93 :     sprintf( szValue, "%.14g", dfMax );
    3896              93 :     SetMetadataItem( "STATISTICS_MAXIMUM", szValue );
    3897                 : 
    3898              93 :     sprintf( szValue, "%.14g", dfMean );
    3899              93 :     SetMetadataItem( "STATISTICS_MEAN", szValue );
    3900                 : 
    3901              93 :     sprintf( szValue, "%.14g", dfStdDev );
    3902              93 :     SetMetadataItem( "STATISTICS_STDDEV", szValue );
    3903                 : 
    3904              93 :     return CE_None;
    3905                 : }
    3906                 : 
    3907                 : /************************************************************************/
    3908                 : /*                      GDALSetRasterStatistics()                       */
    3909                 : /************************************************************************/
    3910                 : 
    3911                 : /**
    3912                 :  * \brief Set statistics on band.
    3913                 :  *
    3914                 :  * @see GDALRasterBand::SetStatistics()
    3915                 :  */
    3916                 : 
    3917               0 : CPLErr CPL_STDCALL GDALSetRasterStatistics( 
    3918                 :         GDALRasterBandH hBand,  
    3919                 :         double dfMin, double dfMax, double dfMean, double dfStdDev )
    3920                 : 
    3921                 : {
    3922               0 :     VALIDATE_POINTER1( hBand, "GDALSetRasterStatistics", CE_Failure );
    3923                 : 
    3924               0 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    3925               0 :     return poBand->SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
    3926                 : }
    3927                 : 
    3928                 : /************************************************************************/
    3929                 : /*                        ComputeRasterMinMax()                         */
    3930                 : /************************************************************************/
    3931                 : 
    3932                 : /**
    3933                 :  * \brief Compute the min/max values for a band.
    3934                 :  * 
    3935                 :  * If approximate is OK, then the band's GetMinimum()/GetMaximum() will
    3936                 :  * be trusted.  If it doesn't work, a subsample of blocks will be read to
    3937                 :  * get an approximate min/max.  If the band has a nodata value it will
    3938                 :  * be excluded from the minimum and maximum.
    3939                 :  *
    3940                 :  * If bApprox is FALSE, then all pixels will be read and used to compute
    3941                 :  * an exact range.
    3942                 :  *
    3943                 :  * This method is the same as the C function GDALComputeRasterMinMax().
    3944                 :  * 
    3945                 :  * @param bApproxOK TRUE if an approximate (faster) answer is OK, otherwise
    3946                 :  * FALSE.
    3947                 :  * @param adfMinMax the array in which the minimum (adfMinMax[0]) and the
    3948                 :  * maximum (adfMinMax[1]) are returned.
    3949                 :  *
    3950                 :  * @return CE_None on success or CE_Failure on failure.
    3951                 :  */
    3952                 : 
    3953                 : 
    3954             804 : CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
    3955                 :                                             double adfMinMax[2] )
    3956                 : {
    3957             804 :     double  dfMin = 0.0;
    3958             804 :     double  dfMax = 0.0;
    3959                 : 
    3960                 : /* -------------------------------------------------------------------- */
    3961                 : /*      Does the driver already know the min/max?                       */
    3962                 : /* -------------------------------------------------------------------- */
    3963             804 :     if( bApproxOK )
    3964                 :     {
    3965                 :         int          bSuccessMin, bSuccessMax;
    3966                 : 
    3967               0 :         dfMin = GetMinimum( &bSuccessMin );
    3968               0 :         dfMax = GetMaximum( &bSuccessMax );
    3969                 : 
    3970               0 :         if( bSuccessMin && bSuccessMax )
    3971                 :         {
    3972               0 :             adfMinMax[0] = dfMin;
    3973               0 :             adfMinMax[1] = dfMax;
    3974               0 :             return CE_None;
    3975                 :         }
    3976                 :     }
    3977                 :     
    3978                 : /* -------------------------------------------------------------------- */
    3979                 : /*      If we have overview bands, use them for min/max.                */
    3980                 : /* -------------------------------------------------------------------- */
    3981             804 :     if ( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
    3982                 :     {
    3983                 :         GDALRasterBand *poBand;
    3984                 : 
    3985               0 :         poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
    3986                 : 
    3987               0 :         if ( poBand != this )
    3988               0 :             return poBand->ComputeRasterMinMax( FALSE, adfMinMax );
    3989                 :     }
    3990                 :     
    3991                 : /* -------------------------------------------------------------------- */
    3992                 : /*      Read actual data and compute minimum and maximum.               */
    3993                 : /* -------------------------------------------------------------------- */
    3994             804 :     int     bGotNoDataValue, bFirstValue = TRUE;
    3995                 :     double  dfNoDataValue;
    3996                 : 
    3997             804 :     dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
    3998             804 :     bGotNoDataValue = bGotNoDataValue && !CPLIsNan(dfNoDataValue);
    3999                 : 
    4000             804 :     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
    4001             804 :     int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
    4002                 :     
    4003             804 :     if ( bApproxOK && HasArbitraryOverviews() )
    4004                 :     {
    4005                 : /* -------------------------------------------------------------------- */
    4006                 : /*      Figure out how much the image should be reduced to get an       */
    4007                 : /*      approximate value.                                              */
    4008                 : /* -------------------------------------------------------------------- */
    4009                 :         void    *pData;
    4010                 :         int     nXReduced, nYReduced;
    4011                 :         double  dfReduction = sqrt(
    4012               0 :             (double)nRasterXSize * nRasterYSize / GDALSTAT_APPROX_NUMSAMPLES );
    4013                 : 
    4014               0 :         if ( dfReduction > 1.0 )
    4015                 :         {
    4016               0 :             nXReduced = (int)( nRasterXSize / dfReduction );
    4017               0 :             nYReduced = (int)( nRasterYSize / dfReduction );
    4018                 : 
    4019                 :             // Catch the case of huge resizing ratios here
    4020               0 :             if ( nXReduced == 0 )
    4021               0 :                 nXReduced = 1;
    4022               0 :             if ( nYReduced == 0 )
    4023               0 :                 nYReduced = 1;
    4024                 :         }
    4025                 :         else
    4026                 :         {
    4027               0 :             nXReduced = nRasterXSize;
    4028               0 :             nYReduced = nRasterYSize;
    4029                 :         }
    4030                 : 
    4031                 :         pData =
    4032               0 :             CPLMalloc(GDALGetDataTypeSize(eDataType)/8 * nXReduced * nYReduced);
    4033                 : 
    4034                 :         CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
    4035               0 :                    nXReduced, nYReduced, eDataType, 0, 0 );
    4036               0 :         if ( eErr != CE_None )
    4037                 :         {
    4038               0 :             CPLFree(pData);
    4039               0 :             return eErr;
    4040                 :         }
    4041                 :         
    4042                 :         /* this isn't the fastest way to do this, but is easier for now */
    4043               0 :         for( int iY = 0; iY < nYReduced; iY++ )
    4044                 :         {
    4045               0 :             for( int iX = 0; iX < nXReduced; iX++ )
    4046                 :             {
    4047               0 :                 int    iOffset = iX + iY * nXReduced;
    4048               0 :                 double dfValue = 0.0;
    4049                 : 
    4050               0 :                 switch( eDataType )
    4051                 :                 {
    4052                 :                   case GDT_Byte:
    4053                 :                   {
    4054               0 :                     if (bSignedByte)
    4055               0 :                         dfValue = ((signed char *)pData)[iOffset];
    4056                 :                     else
    4057               0 :                         dfValue = ((GByte *)pData)[iOffset];
    4058               0 :                     break;
    4059                 :                   }
    4060                 :                   case GDT_UInt16:
    4061               0 :                     dfValue = ((GUInt16 *)pData)[iOffset];
    4062               0 :                     break;
    4063                 :                   case GDT_Int16:
    4064               0 :                     dfValue = ((GInt16 *)pData)[iOffset];
    4065               0 :                     break;
    4066                 :                   case GDT_UInt32:
    4067               0 :                     dfValue = ((GUInt32 *)pData)[iOffset];
    4068               0 :                     break;
    4069                 :                   case GDT_Int32:
    4070               0 :                     dfValue = ((GInt32 *)pData)[iOffset];
    4071               0 :                     break;
    4072                 :                   case GDT_Float32:
    4073               0 :                     dfValue = ((float *)pData)[iOffset];
    4074               0 :                     if (CPLIsNan(dfValue))
    4075               0 :                         continue;
    4076               0 :                     break;
    4077                 :                   case GDT_Float64:
    4078               0 :                     dfValue = ((double *)pData)[iOffset];
    4079               0 :                     if (CPLIsNan(dfValue))
    4080               0 :                         continue;
    4081               0 :                     break;
    4082                 :                   case GDT_CInt16:
    4083               0 :                     dfValue = ((GInt16 *)pData)[iOffset*2];
    4084               0 :                     break;
    4085                 :                   case GDT_CInt32:
    4086               0 :                     dfValue = ((GInt32 *)pData)[iOffset*2];
    4087               0 :                     break;
    4088                 :                   case GDT_CFloat32:
    4089               0 :                     dfValue = ((float *)pData)[iOffset*2];
    4090               0 :                     if( CPLIsNan(dfValue) )
    4091               0 :                         continue;
    4092               0 :                     break;
    4093                 :                   case GDT_CFloat64:
    4094               0 :                     dfValue = ((double *)pData)[iOffset*2];
    4095               0 :                     if( CPLIsNan(dfValue) )
    4096               0 :                         continue;
    4097               0 :                     break;
    4098                 :                   default:
    4099               0 :                     CPLAssert( FALSE );
    4100                 :                 }
    4101                 :                 
    4102               0 :                 if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
    4103               0 :                     continue;
    4104                 : 
    4105               0 :                 if( bFirstValue )
    4106                 :                 {
    4107               0 :                     dfMin = dfMax = dfValue;
    4108               0 :                     bFirstValue = FALSE;
    4109                 :                 }
    4110                 :                 else
    4111                 :                 {
    4112               0 :                     dfMin = MIN(dfMin,dfValue);
    4113               0 :                     dfMax = MAX(dfMax,dfValue);
    4114                 :                 }
    4115                 :             }
    4116                 :         }
    4117                 : 
    4118               0 :         CPLFree( pData );
    4119                 :     }
    4120                 : 
    4121                 :     else    // No arbitrary overviews
    4122                 :     {
    4123                 :         int     nSampleRate;
    4124                 : 
    4125             804 :         if( !InitBlockInfo() )
    4126               0 :             return CE_Failure;
    4127                 : 
    4128                 : /* -------------------------------------------------------------------- */
    4129                 : /*      Figure out the ratio of blocks we will read to get an           */
    4130                 : /*      approximate value.                                              */
    4131                 : /* -------------------------------------------------------------------- */
    4132             804 :         if ( bApproxOK )
    4133                 :         {
    4134                 :             nSampleRate = 
    4135               0 :                 (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn));
    4136                 :         }
    4137                 :         else
    4138             804 :             nSampleRate = 1;
    4139                 :         
    4140           21297 :         for( int iSampleBlock = 0; 
    4141                 :              iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
    4142                 :              iSampleBlock += nSampleRate )
    4143                 :         {
    4144                 :             int  iXBlock, iYBlock, nXCheck, nYCheck;
    4145                 :             GDALRasterBlock *poBlock;
    4146                 :             void* pData;
    4147                 : 
    4148           20493 :             iYBlock = iSampleBlock / nBlocksPerRow;
    4149           20493 :             iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
    4150                 :             
    4151           20493 :             poBlock = GetLockedBlockRef( iXBlock, iYBlock );
    4152           20493 :             if( poBlock == NULL )
    4153               0 :                 continue;
    4154           20493 :             if( poBlock->GetDataRef() == NULL )
    4155                 :             {
    4156               0 :                 poBlock->DropLock();
    4157               0 :                 continue;
    4158                 :             }
    4159                 :             
    4160           20493 :             pData = poBlock->GetDataRef();
    4161                 :             
    4162           20493 :             if( (iXBlock+1) * nBlockXSize > GetXSize() )
    4163             772 :                 nXCheck = GetXSize() - iXBlock * nBlockXSize;
    4164                 :             else
    4165           19721 :                 nXCheck = nBlockXSize;
    4166                 : 
    4167           20493 :             if( (iYBlock+1) * nBlockYSize > GetYSize() )
    4168             110 :                 nYCheck = GetYSize() - iYBlock * nBlockYSize;
    4169                 :             else
    4170           20383 :                 nYCheck = nBlockYSize;
    4171                 :                 
    4172                 :             /* this isn't the fastest way to do this, but is easier for now */
    4173          191726 :             for( int iY = 0; iY < nYCheck; iY++ )
    4174                 :             {
    4175         6233428 :                 for( int iX = 0; iX < nXCheck; iX++ )
    4176                 :                 {
    4177         6062195 :                     int    iOffset = iX + iY * nBlockXSize;
    4178         6062195 :                     double dfValue = 0.0;
    4179                 : 
    4180         6062195 :                     switch( eDataType )
    4181                 :                     {
    4182                 :                       case GDT_Byte:
    4183                 :                       {
    4184         3606924 :                         if (bSignedByte)
    4185            3600 :                             dfValue = ((signed char *) pData)[iOffset];
    4186                 :                         else
    4187         3603324 :                             dfValue = ((GByte *) pData)[iOffset];
    4188         3606924 :                         break;
    4189                 :                       }
    4190                 :                       case GDT_UInt16:
    4191           26900 :                         dfValue = ((GUInt16 *) pData)[iOffset];
    4192           26900 :                         break;
    4193                 :                       case GDT_Int16:
    4194         1743494 :                         dfValue = ((GInt16 *) pData)[iOffset];
    4195         1743494 :                         break;
    4196                 :                       case GDT_UInt32:
    4197           13300 :                         dfValue = ((GUInt32 *) pData)[iOffset];
    4198           13300 :                         break;
    4199                 :                       case GDT_Int32:
    4200           52670 :                         dfValue = ((GInt32 *) pData)[iOffset];
    4201           52670 :                         break;
    4202                 :                       case GDT_Float32:
    4203          576282 :                         dfValue = ((float *) pData)[iOffset];
    4204          576282 :                         if( CPLIsNan(dfValue) )
    4205               0 :                             continue;
    4206          576282 :                         break;
    4207                 :                       case GDT_Float64:
    4208           23025 :                         dfValue = ((double *) pData)[iOffset];
    4209           23025 :                         if( CPLIsNan(dfValue) )
    4210               0 :                             continue;
    4211           23025 :                         break;
    4212                 :                       case GDT_CInt16:
    4213            2800 :                         dfValue = ((GInt16 *) pData)[iOffset*2];
    4214            2800 :                         break;
    4215                 :                       case GDT_CInt32:
    4216            2800 :                         dfValue = ((GInt32 *) pData)[iOffset*2];
    4217            2800 :                         break;
    4218                 :                       case GDT_CFloat32:
    4219            6800 :                         dfValue = ((float *) pData)[iOffset*2];
    4220            6800 :                         if( CPLIsNan(dfValue) )
    4221               0 :                             continue;
    4222            6800 :                         break;
    4223                 :                       case GDT_CFloat64:
    4224            7200 :                         dfValue = ((double *) pData)[iOffset*2];
    4225            7200 :                         if( CPLIsNan(dfValue) )
    4226               0 :                             continue;
    4227            7200 :                         break;
    4228                 :                       default:
    4229               0 :                         CPLAssert( FALSE );
    4230                 :                     }
    4231                 :                     
    4232         6062195 :                     if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
    4233          432259 :                         continue;
    4234                 : 
    4235         5629936 :                     if( bFirstValue )
    4236                 :                     {
    4237             804 :                         dfMin = dfMax = dfValue;
    4238             804 :                         bFirstValue = FALSE;
    4239                 :                     }
    4240                 :                     else
    4241                 :                     {
    4242         5629132 :                         dfMin = MIN(dfMin,dfValue);
    4243         5629132 :                         dfMax = MAX(dfMax,dfValue);
    4244                 :                     }
    4245                 :                 }
    4246                 :             }
    4247                 : 
    4248           20493 :             poBlock->DropLock();
    4249                 :         }
    4250                 :     }
    4251                 : 
    4252             804 :     adfMinMax[0] = dfMin;
    4253             804 :     adfMinMax[1] = dfMax;
    4254                 : 
    4255             804 :     if (bFirstValue)
    4256                 :     {
    4257                 :         ReportError( CE_Failure, CPLE_AppDefined,
    4258               0 :             "Failed to compute min/max, no valid pixels found in sampling." );
    4259               0 :         return CE_Failure;
    4260                 :     }
    4261                 :     else
    4262                 :     {
    4263             804 :         return CE_None;
    4264                 :     }
    4265                 : }
    4266                 : 
    4267                 : /************************************************************************/
    4268                 : /*                      GDALComputeRasterMinMax()                       */
    4269                 : /************************************************************************/
    4270                 : 
    4271                 : /**
    4272                 :  * \brief Compute the min/max values for a band.
    4273                 :  * 
    4274                 :  * @see GDALRasterBand::ComputeRasterMinMax()
    4275                 :  */
    4276                 : 
    4277                 : void CPL_STDCALL 
    4278             804 : GDALComputeRasterMinMax( GDALRasterBandH hBand, int bApproxOK, 
    4279                 :                          double adfMinMax[2] )
    4280                 : 
    4281                 : {
    4282             804 :     VALIDATE_POINTER0( hBand, "GDALComputeRasterMinMax" );
    4283                 : 
    4284             804 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    4285             804 :     poBand->ComputeRasterMinMax( bApproxOK, adfMinMax );
    4286                 : }
    4287                 : 
    4288                 : /************************************************************************/
    4289                 : /*                        SetDefaultHistogram()                         */
    4290                 : /************************************************************************/
    4291                 : 
    4292                 : /* FIXME : add proper documentation */
    4293                 : /**
    4294                 :  * \brief Set default histogram.
    4295                 :  */
    4296               0 : CPLErr GDALRasterBand::SetDefaultHistogram( double dfMin, double dfMax, 
    4297                 :                                             int nBuckets, int *panHistogram )
    4298                 : 
    4299                 : {
    4300               0 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    4301                 :         ReportError( CE_Failure, CPLE_NotSupported,
    4302               0 :                   "SetDefaultHistogram() not implemented for this format." );
    4303                 : 
    4304               0 :     return CE_Failure;
    4305                 : }
    4306                 : 
    4307                 : /************************************************************************/
    4308                 : /*                      GDALSetDefaultHistogram()                       */
    4309                 : /************************************************************************/
    4310                 : 
    4311                 : /**
    4312                 :  * \brief Set default histogram.
    4313                 :  *
    4314                 :  * @see GDALRasterBand::SetDefaultHistogram()
    4315                 :  */
    4316                 : 
    4317               0 : CPLErr CPL_STDCALL GDALSetDefaultHistogram( GDALRasterBandH hBand, 
    4318                 :                                             double dfMin, double dfMax, 
    4319                 :                                             int nBuckets, int *panHistogram )
    4320                 : 
    4321                 : {
    4322               0 :     VALIDATE_POINTER1( hBand, "GDALSetDefaultHistogram", CE_Failure );
    4323                 : 
    4324               0 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    4325               0 :     return poBand->SetDefaultHistogram( dfMin, dfMax, nBuckets, panHistogram );
    4326                 : }
    4327                 : 
    4328                 : /************************************************************************/
    4329                 : /*                           GetDefaultRAT()                            */
    4330                 : /************************************************************************/
    4331                 : 
    4332                 : /**
    4333                 :  * \brief Fetch default Raster Attribute Table.
    4334                 :  *
    4335                 :  * A RAT will be returned if there is a default one associated with the
    4336                 :  * band, otherwise NULL is returned.  The returned RAT is owned by the
    4337                 :  * band and should not be deleted, or altered by the application. 
    4338                 :  * 
    4339                 :  * @return NULL, or a pointer to an internal RAT owned by the band.
    4340                 :  */
    4341                 : 
    4342             218 : const GDALRasterAttributeTable *GDALRasterBand::GetDefaultRAT()
    4343                 : 
    4344                 : {
    4345             218 :     return NULL;
    4346                 : }
    4347                 : 
    4348                 : /************************************************************************/
    4349                 : /*                         GDALGetDefaultRAT()                          */
    4350                 : /************************************************************************/
    4351                 : 
    4352                 : /**
    4353                 :  * \brief Fetch default Raster Attribute Table.
    4354                 :  *
    4355                 :  * @see GDALRasterBand::GetDefaultRAT()
    4356                 :  */
    4357                 : 
    4358              44 : GDALRasterAttributeTableH CPL_STDCALL GDALGetDefaultRAT( GDALRasterBandH hBand)
    4359                 : 
    4360                 : {
    4361              44 :     VALIDATE_POINTER1( hBand, "GDALGetDefaultRAT", NULL );
    4362                 : 
    4363              44 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    4364              44 :     return (GDALRasterAttributeTableH) poBand->GetDefaultRAT();
    4365                 : }
    4366                 : 
    4367                 : /************************************************************************/
    4368                 : /*                           SetDefaultRAT()                            */
    4369                 : /************************************************************************/
    4370                 : 
    4371                 : /**
    4372                 :  * \brief Set default Raster Attribute Table.
    4373                 :  *
    4374                 :  * Associates a default RAT with the band.  If not implemented for the
    4375                 :  * format a CPLE_NotSupported error will be issued.  If successful a copy
    4376                 :  * of the RAT is made, the original remains owned by the caller.
    4377                 :  *
    4378                 :  * @param poRAT the RAT to assign to the band.
    4379                 :  *
    4380                 :  * @return CE_None on success or CE_Failure if unsupported or otherwise 
    4381                 :  * failing.
    4382                 :  */
    4383                 : 
    4384               0 : CPLErr GDALRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
    4385                 : 
    4386                 : {
    4387               0 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    4388                 :         ReportError( CE_Failure, CPLE_NotSupported,
    4389               0 :                   "SetDefaultRAT() not implemented for this format." );
    4390                 : 
    4391               0 :     return CE_Failure;
    4392                 : }
    4393                 : 
    4394                 : /************************************************************************/
    4395                 : /*                         GDALSetDefaultRAT()                          */
    4396                 : /************************************************************************/
    4397                 : 
    4398                 : /**
    4399                 :  * \brief Set default Raster Attribute Table.
    4400                 :  *
    4401                 :  * @see GDALRasterBand::GDALSetDefaultRAT()
    4402                 :  */
    4403                 : 
    4404               2 : CPLErr CPL_STDCALL GDALSetDefaultRAT( GDALRasterBandH hBand,
    4405                 :                                       GDALRasterAttributeTableH hRAT )
    4406                 : 
    4407                 : {
    4408               2 :     VALIDATE_POINTER1( hBand, "GDALSetDefaultRAT", CE_Failure );
    4409               2 :     VALIDATE_POINTER1( hRAT, "GDALSetDefaultRAT", CE_Failure );
    4410                 : 
    4411               2 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    4412                 : 
    4413                 :     return poBand->SetDefaultRAT( 
    4414               2 :         static_cast<GDALRasterAttributeTable *>(hRAT) );
    4415                 : }
    4416                 : 
    4417                 : /************************************************************************/
    4418                 : /*                            GetMaskBand()                             */
    4419                 : /************************************************************************/
    4420                 : 
    4421                 : /**
    4422                 :  * \brief Return the mask band associated with the band.
    4423                 :  *
    4424                 :  * The GDALRasterBand class includes a default implementation of GetMaskBand() that
    4425                 :  * returns one of four default implementations :
    4426                 :  * <ul>
    4427                 :  * <li>If a corresponding .msk file exists it will be used for the mask band.</li>
    4428                 :  * <li>If the dataset has a NODATA_VALUES metadata item, an instance of the
    4429                 :  *     new GDALNoDataValuesMaskBand class will be returned.
    4430                 :  *     GetMaskFlags() will return GMF_NODATA | GMF_PER_DATASET. @since GDAL 1.6.0</li>
    4431                 :  * <li>If the band has a nodata value set, an instance of the new
    4432                 :  *     GDALNodataMaskRasterBand class will be returned.
    4433                 :  *     GetMaskFlags() will return GMF_NODATA.</li>
    4434                 :  * <li>If there is no nodata value, but the dataset has an alpha band that seems
    4435                 :  *     to apply to this band (specific rules yet to be determined) and that is
    4436                 :  *     of type GDT_Byte then that alpha band will be returned, and the flags
    4437                 :  *     GMF_PER_DATASET and GMF_ALPHA will be returned in the flags.</li>
    4438                 :  * <li>If neither of the above apply, an instance of the new GDALAllValidRasterBand
    4439                 :  *     class will be returned that has 255 values for all pixels.
    4440                 :  *     The null flags will return GMF_ALL_VALID.</li>
    4441                 :  * </ul>
    4442                 :  *
    4443                 :  * Note that the GetMaskBand() should always return a GDALRasterBand mask, even if it is only
    4444                 :  * an all 255 mask with the flags indicating GMF_ALL_VALID. 
    4445                 :  *
    4446                 :  * @return a valid mask band.
    4447                 :  *
    4448                 :  * @since GDAL 1.5.0
    4449                 :  *
    4450                 :  * @see http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask
    4451                 :  *
    4452                 :  */
    4453            1375 : GDALRasterBand *GDALRasterBand::GetMaskBand()
    4454                 : 
    4455                 : {
    4456            1375 :     if( poMask != NULL )
    4457             149 :         return poMask;
    4458                 : 
    4459                 : /* -------------------------------------------------------------------- */
    4460                 : /*      Check for a mask in a .msk file.                                */
    4461                 : /* -------------------------------------------------------------------- */
    4462            1226 :     GDALDataset *poDS = GetDataset();
    4463                 : 
    4464            1226 :     if( poDS != NULL && poDS->oOvManager.HaveMaskFile() )
    4465                 :     {
    4466              15 :         poMask = poDS->oOvManager.GetMaskBand( nBand );
    4467              15 :         if( poMask != NULL )
    4468                 :         {
    4469              15 :             nMaskFlags = poDS->oOvManager.GetMaskFlags( nBand );
    4470              15 :             return poMask;
    4471                 :         }
    4472                 :     }
    4473                 : 
    4474                 : /* -------------------------------------------------------------------- */
    4475                 : /*      Check for NODATA_VALUES metadata.                               */
    4476                 : /* -------------------------------------------------------------------- */
    4477            1211 :     if (poDS != NULL)
    4478                 :     {
    4479            1210 :         const char* pszNoDataValues = poDS->GetMetadataItem("NODATA_VALUES");
    4480            1210 :         if (pszNoDataValues != NULL)
    4481                 :         {
    4482              41 :             char** papszNoDataValues = CSLTokenizeStringComplex(pszNoDataValues, " ", FALSE, FALSE);
    4483                 : 
    4484                 :             /* Make sure we have as many values as bands */
    4485              41 :             if (CSLCount(papszNoDataValues) == poDS->GetRasterCount() && poDS->GetRasterCount() != 0)
    4486                 :             {
    4487                 :                 /* Make sure that all bands have the same data type */
    4488                 :                 /* This is cleraly not a fundamental condition, just a condition to make implementation */
    4489                 :                 /* easier. */
    4490                 :                 int i;
    4491              41 :                 GDALDataType eDT = GDT_Unknown;
    4492             164 :                 for(i=0;i<poDS->GetRasterCount();i++)
    4493                 :                 {
    4494             123 :                     if (i == 0)
    4495              41 :                         eDT = poDS->GetRasterBand(1)->GetRasterDataType();
    4496              82 :                     else if (eDT != poDS->GetRasterBand(i + 1)->GetRasterDataType())
    4497                 :                     {
    4498               0 :                         break;
    4499                 :                     }
    4500                 :                 }
    4501              41 :                 if (i == poDS->GetRasterCount())
    4502                 :                 {
    4503              41 :                     nMaskFlags = GMF_NODATA | GMF_PER_DATASET;
    4504              41 :                     poMask = new GDALNoDataValuesMaskBand ( poDS );
    4505              41 :                     bOwnMask = true;
    4506              41 :                     CSLDestroy(papszNoDataValues);
    4507              41 :                     return poMask;
    4508                 :                 }
    4509                 :                 else
    4510                 :                 {
    4511                 :                     ReportError(CE_Warning, CPLE_AppDefined,
    4512               0 :                             "All bands should have the same type in order the NODATA_VALUES metadata item to be used as a mask.");
    4513                 :                 }
    4514                 :             }
    4515                 :             else
    4516                 :             {
    4517                 :                 ReportError(CE_Warning, CPLE_AppDefined,
    4518                 :                         "NODATA_VALUES metadata item doesn't have the same number of values as the number of bands.\n"
    4519               0 :                         "Ignoring it for mask.");
    4520                 :             }
    4521                 : 
    4522               0 :             CSLDestroy(papszNoDataValues);
    4523                 :         }
    4524                 :     }
    4525                 : 
    4526                 : /* -------------------------------------------------------------------- */
    4527                 : /*      Check for nodata case.                                          */
    4528                 : /* -------------------------------------------------------------------- */
    4529                 :     int bHaveNoData;
    4530                 : 
    4531            1170 :     GetNoDataValue( &bHaveNoData );
    4532                 :     
    4533            1170 :     if( bHaveNoData )
    4534                 :     {
    4535              89 :         nMaskFlags = GMF_NODATA;
    4536              89 :         poMask = new GDALNoDataMaskBand( this );
    4537              89 :         bOwnMask = true;
    4538              89 :         return poMask;
    4539                 :     }
    4540                 : 
    4541                 : /* -------------------------------------------------------------------- */
    4542                 : /*      Check for alpha case.                                           */
    4543                 : /* -------------------------------------------------------------------- */
    4544            1099 :     if( poDS != NULL 
    4545                 :         && poDS->GetRasterCount() == 2
    4546                 :         && this == poDS->GetRasterBand(1)
    4547              18 :         && poDS->GetRasterBand(2)->GetColorInterpretation() == GCI_AlphaBand
    4548                 :         && poDS->GetRasterBand(2)->GetRasterDataType() == GDT_Byte )
    4549                 :     {
    4550               2 :         nMaskFlags = GMF_ALPHA | GMF_PER_DATASET;
    4551               2 :         poMask = poDS->GetRasterBand(2);
    4552               2 :         return poMask;
    4553                 :     }
    4554                 : 
    4555            1129 :     if( poDS != NULL 
    4556                 :         && poDS->GetRasterCount() == 4
    4557                 :         && (this == poDS->GetRasterBand(1)
    4558                 :             || this == poDS->GetRasterBand(2)
    4559                 :             || this == poDS->GetRasterBand(3))
    4560              50 :         && poDS->GetRasterBand(4)->GetColorInterpretation() == GCI_AlphaBand
    4561                 :         && poDS->GetRasterBand(4)->GetRasterDataType() == GDT_Byte )
    4562                 :     {
    4563              23 :         nMaskFlags = GMF_ALPHA | GMF_PER_DATASET;
    4564              23 :         poMask = poDS->GetRasterBand(4);
    4565              23 :         return poMask;
    4566                 :     }
    4567                 : 
    4568                 : /* -------------------------------------------------------------------- */
    4569                 : /*      Fallback to all valid case.                                     */
    4570                 : /* -------------------------------------------------------------------- */
    4571            1056 :     nMaskFlags = GMF_ALL_VALID;
    4572            1056 :     poMask = new GDALAllValidMaskBand( this );
    4573            1056 :     bOwnMask = true;
    4574                 : 
    4575            1056 :     return poMask;
    4576                 : }
    4577                 : 
    4578                 : /************************************************************************/
    4579                 : /*                          GDALGetMaskBand()                           */
    4580                 : /************************************************************************/
    4581                 : 
    4582                 : /**
    4583                 :  * \brief Return the mask band associated with the band.
    4584                 :  *
    4585                 :  * @see GDALRasterBand::GetMaskBand()
    4586                 :  */
    4587                 : 
    4588             180 : GDALRasterBandH CPL_STDCALL GDALGetMaskBand( GDALRasterBandH hBand )
    4589                 : 
    4590                 : {
    4591             180 :     VALIDATE_POINTER1( hBand, "GDALGetMaskBand", NULL );
    4592                 : 
    4593             180 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    4594             180 :     return poBand->GetMaskBand();
    4595                 : }
    4596                 : 
    4597                 : /************************************************************************/
    4598                 : /*                            GetMaskFlags()                            */
    4599                 : /************************************************************************/
    4600                 : 
    4601                 : /**
    4602                 :  * \brief Return the status flags of the mask band associated with the band.
    4603                 :  *
    4604                 :  * The GetMaskFlags() method returns an bitwise OR-ed set of status flags with
    4605                 :  * the following available definitions that may be extended in the future:
    4606                 :  * <ul>
    4607                 :  * <li>GMF_ALL_VALID(0x01): There are no invalid pixels, all mask values will be 255.
    4608                 :  *     When used this will normally be the only flag set.</li>
    4609                 :  * <li>GMF_PER_DATASET(0x02): The mask band is shared between all bands on the dataset.</li>
    4610                 :  * <li>GMF_ALPHA(0x04): The mask band is actually an alpha band and may have values
    4611                 :  *     other than 0 and 255.</li>
    4612                 :  * <li>GMF_NODATA(0x08): Indicates the mask is actually being generated from nodata values.
    4613                 :  *     (mutually exclusive of GMF_ALPHA)</li>
    4614                 :  * </ul>
    4615                 :  *
    4616                 :  * The GDALRasterBand class includes a default implementation of GetMaskBand() that
    4617                 :  * returns one of four default implementations :
    4618                 :  * <ul>
    4619                 :  * <li>If a corresponding .msk file exists it will be used for the mask band.</li>
    4620                 :  * <li>If the dataset has a NODATA_VALUES metadata item, an instance of the
    4621                 :  *     new GDALNoDataValuesMaskBand class will be returned.
    4622                 :  *     GetMaskFlags() will return GMF_NODATA | GMF_PER_DATASET. @since GDAL 1.6.0</li>
    4623                 :  * <li>If the band has a nodata value set, an instance of the new
    4624                 :  *     GDALNodataMaskRasterBand class will be returned.
    4625                 :  *     GetMaskFlags() will return GMF_NODATA.</li>
    4626                 :  * <li>If there is no nodata value, but the dataset has an alpha band that seems
    4627                 :  *     to apply to this band (specific rules yet to be determined) and that is
    4628                 :  *     of type GDT_Byte then that alpha band will be returned, and the flags
    4629                 :  *     GMF_PER_DATASET and GMF_ALPHA will be returned in the flags.</li>
    4630                 :  * <li>If neither of the above apply, an instance of the new GDALAllValidRasterBand
    4631                 :  *     class will be returned that has 255 values for all pixels.
    4632                 :  *     The null flags will return GMF_ALL_VALID.</li>
    4633                 :  * </ul>
    4634                 :  *
    4635                 :  * @since GDAL 1.5.0
    4636                 :  *
    4637                 :  * @return a valid mask band.
    4638                 :  *
    4639                 :  * @see http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask
    4640                 :  *
    4641                 :  */
    4642            3828 : int GDALRasterBand::GetMaskFlags()
    4643                 : 
    4644                 : {
    4645                 :     // If we don't have a band yet, force this now so that the masks value
    4646                 :     // will be initialized.
    4647                 : 
    4648            3828 :     if( poMask == NULL )
    4649            1205 :         GetMaskBand();
    4650                 : 
    4651            3828 :     return nMaskFlags;
    4652                 : }
    4653                 : 
    4654                 : /************************************************************************/
    4655                 : /*                          GDALGetMaskFlags()                          */
    4656                 : /************************************************************************/
    4657                 : 
    4658                 : /**
    4659                 :  * \brief Return the status flags of the mask band associated with the band.
    4660                 :  *
    4661                 :  * @see GDALRasterBand::GetMaskFlags()
    4662                 :  */
    4663                 : 
    4664            1481 : int CPL_STDCALL GDALGetMaskFlags( GDALRasterBandH hBand )
    4665                 : 
    4666                 : {
    4667            1481 :     VALIDATE_POINTER1( hBand, "GDALGetMaskFlags", GMF_ALL_VALID );
    4668                 : 
    4669            1481 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    4670            1481 :     return poBand->GetMaskFlags();
    4671                 : }
    4672                 : 
    4673                 : /************************************************************************/
    4674                 : /*                           CreateMaskBand()                           */
    4675                 : /************************************************************************/
    4676                 : 
    4677                 : /**
    4678                 :  * \brief Adds a mask band to the current band
    4679                 :  *
    4680                 :  * The default implementation of the CreateMaskBand() method is implemented
    4681                 :  * based on similar rules to the .ovr handling implemented using the
    4682                 :  * GDALDefaultOverviews object. A TIFF file with the extension .msk will
    4683                 :  * be created with the same basename as the original file, and it will have
    4684                 :  * as many bands as the original image (or just one for GMF_PER_DATASET).
    4685                 :  * The mask images will be deflate compressed tiled images with the same
    4686                 :  * block size as the original image if possible.
    4687                 :  *
    4688                 :  * Note that if you got a mask band with a previous call to GetMaskBand(),
    4689                 :  * it might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
    4690                 :  * again.
    4691                 :  *
    4692                 :  * @since GDAL 1.5.0
    4693                 :  *
    4694                 :  * @return CE_None on success or CE_Failure on an error.
    4695                 :  *
    4696                 :  * @see http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask
    4697                 :  *
    4698                 :  */
    4699                 : 
    4700               0 : CPLErr GDALRasterBand::CreateMaskBand( int nFlags )
    4701                 : 
    4702                 : {
    4703               0 :     if( poDS != NULL && poDS->oOvManager.IsInitialized() )
    4704                 :     {
    4705               0 :         CPLErr eErr = poDS->oOvManager.CreateMaskBand( nFlags, nBand );
    4706               0 :         if (eErr != CE_None)
    4707               0 :             return eErr;
    4708                 : 
    4709                 :         /* Invalidate existing raster band mask */
    4710               0 :         if (bOwnMask)
    4711               0 :             delete poMask;
    4712               0 :         bOwnMask = false;
    4713               0 :         poMask = NULL;
    4714                 : 
    4715               0 :         return CE_None;
    4716                 :     }
    4717                 : 
    4718                 :     ReportError( CE_Failure, CPLE_NotSupported,
    4719               0 :               "CreateMaskBand() not supported for this band." );
    4720                 :     
    4721               0 :     return CE_Failure;
    4722                 : }
    4723                 : 
    4724                 : /************************************************************************/
    4725                 : /*                         GDALCreateMaskBand()                         */
    4726                 : /************************************************************************/
    4727                 : 
    4728                 : /**
    4729                 :  * \brief Adds a mask band to the current band
    4730                 :  *
    4731                 :  * @see GDALRasterBand::CreateMaskBand()
    4732                 :  */
    4733                 : 
    4734              12 : CPLErr CPL_STDCALL GDALCreateMaskBand( GDALRasterBandH hBand, int nFlags )
    4735                 : 
    4736                 : {
    4737              12 :     VALIDATE_POINTER1( hBand, "GDALCreateMaskBand", CE_Failure );
    4738                 : 
    4739              12 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    4740              12 :     return poBand->CreateMaskBand( nFlags );
    4741                 : }
    4742                 : 
    4743                 : /************************************************************************/
    4744                 : /*                    GetIndexColorTranslationTo()                      */
    4745                 : /************************************************************************/
    4746                 : 
    4747                 : /**
    4748                 :  * \brief Compute translation table for color tables.
    4749                 :  *
    4750                 :  * When the raster band has a palette index, it may be usefull to compute
    4751                 :  * the "translation" of this palette to the palette of another band.
    4752                 :  * The translation tries to do exact matching first, and then approximate
    4753                 :  * matching if no exact matching is possible.
    4754                 :  * This method returns a table such that table[i] = j where i is an index
    4755                 :  * of the 'this' rasterband and j the corresponding index for the reference
    4756                 :  * rasterband.
    4757                 :  *
    4758                 :  * This method is thought as internal to GDAL and is used for drivers
    4759                 :  * like RPFTOC.
    4760                 :  *
    4761                 :  * The implementation only supports 1-byte palette rasterbands.
    4762                 :  *
    4763                 :  * @param poReferenceBand the raster band
    4764                 :  * @param pTranslationTable an already allocated translation table (at least 256 bytes),
    4765                 :  *                          or NULL to let the method allocate it
    4766                 :  * @param pApproximateMatching a pointer to a flag that is set if the matching
    4767                 :  *                              is approximate. May be NULL.
    4768                 :  *
    4769                 :  * @return a translation table if the two bands are palette index and that they do
    4770                 :  *         not match or NULL in other cases.
    4771                 :  *         The table must be freed with CPLFree if NULL was passed for pTranslationTable.
    4772                 :  */
    4773                 : 
    4774              11 : unsigned char* GDALRasterBand::GetIndexColorTranslationTo(GDALRasterBand* poReferenceBand,
    4775                 :                                                           unsigned char* pTranslationTable,
    4776                 :                                                           int* pApproximateMatching )
    4777                 : {
    4778              11 :     if (poReferenceBand == NULL)
    4779               0 :         return NULL;
    4780                 : 
    4781              22 :     if (poReferenceBand->GetColorInterpretation() == GCI_PaletteIndex &&
    4782              11 :         GetColorInterpretation() == GCI_PaletteIndex &&
    4783                 :         poReferenceBand->GetRasterDataType() == GDT_Byte &&
    4784                 :         GetRasterDataType() == GDT_Byte)
    4785                 :     {
    4786              11 :         GDALColorTable* srcColorTable = GetColorTable();
    4787              11 :         GDALColorTable* destColorTable = poReferenceBand->GetColorTable();
    4788              11 :         if (srcColorTable != NULL && destColorTable != NULL)
    4789                 :         {
    4790              11 :             int nEntries = srcColorTable->GetColorEntryCount();
    4791              11 :             int nRefEntries = destColorTable->GetColorEntryCount();
    4792                 :             int bHasNoDataValueSrc;
    4793              11 :             int noDataValueSrc = (int)GetNoDataValue(&bHasNoDataValueSrc);
    4794                 :             int bHasNoDataValueRef;
    4795              11 :             int noDataValueRef = (int)poReferenceBand->GetNoDataValue(&bHasNoDataValueRef);
    4796                 :             int samePalette;
    4797                 :             int i, j;
    4798                 : 
    4799              11 :             if (pApproximateMatching)
    4800               2 :                 *pApproximateMatching = FALSE;
    4801                 : 
    4802              22 :             if (nEntries == nRefEntries && bHasNoDataValueSrc == bHasNoDataValueRef &&
    4803                 :                 (bHasNoDataValueSrc == FALSE || noDataValueSrc == noDataValueRef))
    4804                 :             {
    4805              11 :                 samePalette = TRUE;
    4806            2749 :                 for(i=0;i<nEntries;i++)
    4807                 :                 {
    4808            2738 :                     if (noDataValueSrc == i)
    4809               2 :                         continue;
    4810            2736 :                     const GDALColorEntry* entry = srcColorTable->GetColorEntry(i);
    4811            2736 :                     const GDALColorEntry* entryRef = destColorTable->GetColorEntry(i);
    4812            2736 :                     if (entry->c1 != entryRef->c1 ||
    4813                 :                         entry->c2 != entryRef->c2 ||
    4814                 :                         entry->c3 != entryRef->c3)
    4815                 :                     {
    4816            2048 :                         samePalette = FALSE;
    4817                 :                     }
    4818                 :                 }
    4819                 :             }
    4820                 :             else
    4821                 :             {
    4822               0 :                 samePalette = FALSE;
    4823                 :             }
    4824              11 :             if (samePalette == FALSE)
    4825                 :             {
    4826               8 :                 if (pTranslationTable == NULL)
    4827               8 :                     pTranslationTable = (unsigned char*)CPLMalloc(256);
    4828                 : 
    4829                 :                 /* Trying to remap the product palette on the subdataset palette */
    4830            2056 :                 for(i=0;i<nEntries;i++)
    4831                 :                 {
    4832            2048 :                     if (bHasNoDataValueSrc && bHasNoDataValueRef && noDataValueSrc == i)
    4833               0 :                         continue;
    4834            2048 :                     const GDALColorEntry* entry = srcColorTable->GetColorEntry(i);
    4835          525614 :                     for(j=0;j<nRefEntries;j++)
    4836                 :                     {
    4837          523572 :                         if (bHasNoDataValueRef && noDataValueRef == j)
    4838               0 :                             continue;
    4839          523572 :                         const GDALColorEntry* entryRef = destColorTable->GetColorEntry(j);
    4840          523572 :                         if (entry->c1 == entryRef->c1 &&
    4841                 :                             entry->c2 == entryRef->c2 &&
    4842                 :                             entry->c3 == entryRef->c3)
    4843                 :                         {
    4844               6 :                             pTranslationTable[i] = (unsigned char) j;
    4845               6 :                             break;
    4846                 :                         }
    4847                 :                     }
    4848            2048 :                     if (j == nEntries)
    4849                 :                     {
    4850                 :                         /* No exact match. Looking for closest color now... */
    4851            2042 :                         int best_j = 0;
    4852            2042 :                         int best_distance = 0;
    4853            2042 :                         if (pApproximateMatching)
    4854               0 :                             *pApproximateMatching = TRUE;
    4855          524794 :                         for(j=0;j<nRefEntries;j++)
    4856                 :                         {
    4857          522752 :                             const GDALColorEntry* entryRef = destColorTable->GetColorEntry(j);
    4858                 :                             int distance = (entry->c1 - entryRef->c1) * (entry->c1 - entryRef->c1) +
    4859                 :                                            (entry->c2 - entryRef->c2) * (entry->c2 - entryRef->c2) +
    4860          522752 :                                            (entry->c3 - entryRef->c3) * (entry->c3 - entryRef->c3);
    4861          522752 :                             if (j == 0 || distance < best_distance)
    4862                 :                             {
    4863           13217 :                                 best_j = j;
    4864           13217 :                                 best_distance = distance;
    4865                 :                             }
    4866                 :                         }
    4867            2042 :                         pTranslationTable[i] = (unsigned char) best_j;
    4868                 :                     }
    4869                 :                 }
    4870               8 :                 if (bHasNoDataValueRef && bHasNoDataValueSrc)
    4871               0 :                     pTranslationTable[noDataValueSrc] = (unsigned char) noDataValueRef;
    4872                 : 
    4873               8 :                 return pTranslationTable;
    4874                 :             }
    4875                 :         }
    4876                 :     }
    4877               3 :     return NULL;
    4878                 : }
    4879                 : 
    4880                 : /************************************************************************/
    4881                 : /*                         SetFlushBlockErr()                           */
    4882                 : /************************************************************************/
    4883                 : 
    4884                 : /**
    4885                 :  * \brief Store that an error occured while writing a dirty block.
    4886                 :  *
    4887                 :  * This function stores the fact that an error occured while writing a dirty
    4888                 :  * block from GDALRasterBlock::FlushCacheBlock(). Indeed when dirty blocks are
    4889                 :  * flushed when the block cache get full, it is not convenient/possible to
    4890                 :  * report that a dirty block could not be written correctly. This function
    4891                 :  * remembers the error and re-issue it from GDALRasterBand::FlushCache(),
    4892                 :  * GDALRasterBand::WriteBlock() and GDALRasterBand::RasterIO(), which are
    4893                 :  * places where the user can easily match the error with the relevant dataset.
    4894                 :  */
    4895                 : 
    4896               0 : void GDALRasterBand::SetFlushBlockErr( CPLErr eErr )
    4897                 : {
    4898               0 :     eFlushBlockErr = eErr;
    4899               0 : }
    4900                 : 
    4901                 : /************************************************************************/
    4902                 : /*                            ReportError()                             */
    4903                 : /************************************************************************/
    4904                 : 
    4905                 : /**
    4906                 :  * \brief Emits an error related to a raster band.
    4907                 :  *
    4908                 :  * This function is a wrapper for regular CPLError(). The only difference
    4909                 :  * with CPLError() is that it prepends the error message with the dataset
    4910                 :  * name and the band number.
    4911                 :  *
    4912                 :  * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
    4913                 :  * @param err_no the error number (CPLE_*) from cpl_error.h.
    4914                 :  * @param fmt a printf() style format string.  Any additional arguments
    4915                 :  * will be treated as arguments to fill in this format in a manner
    4916                 :  * similar to printf().
    4917                 :  *
    4918                 :  * @since GDAL 1.9.0
    4919                 :  */
    4920                 : 
    4921           13226 : void GDALRasterBand::ReportError(CPLErr eErrClass, int err_no, const char *fmt, ...)
    4922                 : {
    4923                 :     va_list args;
    4924                 : 
    4925           13226 :     va_start(args, fmt);
    4926                 : 
    4927                 :     char szNewFmt[256];
    4928           13226 :     const char* pszDSName = poDS ? poDS->GetDescription() : "";
    4929           13226 :     if (strlen(fmt) + strlen(pszDSName) + 20 >= sizeof(szNewFmt) - 1)
    4930               0 :         pszDSName = CPLGetFilename(pszDSName);
    4931           26450 :     if (pszDSName[0] != '\0' &&
    4932                 :         strlen(fmt) + strlen(pszDSName) + 20 < sizeof(szNewFmt) - 1)
    4933                 :     {
    4934                 :         snprintf(szNewFmt, sizeof(szNewFmt), "%s, band %d: %s",
    4935           13224 :                  pszDSName, GetBand(), fmt);
    4936           13224 :         CPLErrorV( eErrClass, err_no, szNewFmt, args );
    4937                 :     }
    4938                 :     else
    4939                 :     {
    4940               2 :         CPLErrorV( eErrClass, err_no, fmt, args );
    4941                 :     }
    4942           13226 :     va_end(args);
    4943           13226 : }

Generated by: LCOV version 1.7