LTP GCOV extension - code coverage report
Current view: directory - gcore - gdalrasterband.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 1309
Code covered: 59.6 % Executed lines: 780

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

Generated by: LTP GCOV extension version 1.5