LCOV - code coverage report
Current view: directory - gcore - gdalrasterband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1296 749 57.8 %
Date: 2010-01-09 Functions: 100 75 75.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdalrasterband.cpp 18500 2010-01-09 18:23:10Z mloskot $
       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 18500 2010-01-09 18:23:10Z mloskot $");
      44                 : 
      45                 : /************************************************************************/
      46                 : /*                           GDALRasterBand()                           */
      47                 : /************************************************************************/
      48                 : 
      49                 : /*! Constructor. Applications should never create GDALRasterBands directly. */
      50                 : 
      51          618000 : GDALRasterBand::GDALRasterBand()
      52                 : 
      53                 : {
      54          618000 :     poDS = NULL;
      55          618000 :     nBand = 0;
      56          618000 :     nRasterXSize = nRasterYSize = 0;
      57                 : 
      58          618000 :     eAccess = GA_ReadOnly;
      59          618000 :     nBlockXSize = nBlockYSize = -1;
      60          618000 :     eDataType = GDT_Byte;
      61                 : 
      62          618000 :     nSubBlocksPerRow = nBlocksPerRow = 0;
      63          618000 :     nSubBlocksPerColumn = nBlocksPerColumn = 0;
      64                 : 
      65          618000 :     bSubBlockingActive = FALSE;
      66          618000 :     papoBlocks = NULL;
      67                 : 
      68          618000 :     poMask = NULL;
      69          618000 :     bOwnMask = false;
      70          618000 :     nMaskFlags = 0;
      71                 : 
      72          618000 :     nBlockReads = 0;
      73                 :     bForceCachedIO =  CSLTestBoolean( 
      74          618000 :         CPLGetConfigOption( "GDAL_FORCE_CACHING", "NO") );
      75          618000 : }
      76                 : 
      77                 : /************************************************************************/
      78                 : /*                          ~GDALRasterBand()                           */
      79                 : /************************************************************************/
      80                 : 
      81                 : /*! Destructor. Applications should never destroy GDALRasterBands directly,
      82                 :     instead destroy the GDALDataset. */
      83                 : 
      84          617997 : GDALRasterBand::~GDALRasterBand()
      85                 : 
      86                 : {
      87          617997 :     FlushCache();
      88                 : 
      89          617997 :     CPLFree( papoBlocks );
      90                 : 
      91          617997 :     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              44 :                   poDS->GetDescription() );
      97                 :     }
      98                 : 
      99          617997 :     if( bOwnMask )
     100                 :     {
     101             470 :         delete poMask;
     102             470 :         poMask = NULL;
     103             470 :         nMaskFlags = 0;
     104             470 :         bOwnMask = false;
     105                 :     }
     106          617997 : }
     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          396718 : 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                 :                                  int nLineSpace )
     183                 : 
     184                 : {
     185                 : 
     186          396718 :     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                 : /*      If pixel and line spaceing are defaulted assign reasonable      */
     195                 : /*      value assuming a packed buffer.                                 */
     196                 : /* -------------------------------------------------------------------- */
     197          396718 :     if( nPixelSpace == 0 )
     198          386698 :         nPixelSpace = GDALGetDataTypeSize( eBufType ) / 8;
     199                 :     
     200          396718 :     if( nLineSpace == 0 )
     201                 :     {
     202          386897 :         if (nPixelSpace > INT_MAX / nBufXSize)
     203                 :         {
     204                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     205               0 :                       "Int overflow : %d x %d", nPixelSpace, nBufXSize );
     206               0 :             return CE_Failure;
     207                 :         }
     208          386897 :         nLineSpace = nPixelSpace * nBufXSize;
     209                 :     }
     210                 :     
     211                 : /* -------------------------------------------------------------------- */
     212                 : /*      Some size values are "noop".  Lets just return to avoid         */
     213                 : /*      stressing lower level functions.                                */
     214                 : /* -------------------------------------------------------------------- */
     215          396718 :     if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
     216                 :     {
     217                 :         CPLDebug( "GDAL", 
     218                 :                   "RasterIO() skipped for odd window or buffer size.\n"
     219                 :                   "  Window = (%d,%d)x%dx%d\n"
     220                 :                   "  Buffer = %dx%d\n",
     221                 :                   nXOff, nYOff, nXSize, nYSize, 
     222               0 :                   nBufXSize, nBufYSize );
     223                 : 
     224               0 :         return CE_None;
     225                 :     }
     226                 :     
     227                 : /* -------------------------------------------------------------------- */
     228                 : /*      Do some validation of parameters.                               */
     229                 : /* -------------------------------------------------------------------- */
     230          396718 :     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           13211 :                   nXOff, nYOff, nXSize, nYSize, nRasterXSize, nRasterYSize );
     237           13211 :         return CE_Failure;
     238                 :     }
     239                 : 
     240          383507 :     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          383507 :     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          383485 :                           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          336002 : 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                 :               int nPixelSpace, int nLineSpace )
     277                 :     
     278                 : {
     279          336002 :     VALIDATE_POINTER1( hBand, "GDALRasterIO", CE_Failure );
     280                 : 
     281          336002 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
     282                 : 
     283                 :     return( poBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
     284                 :                               pData, nBufXSize, nBufYSize, eBufType,
     285          336002 :                               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             179 : CPLErr GDALRasterBand::ReadBlock( int nXBlockOff, int nYBlockOff,
     376                 :                                    void * pImage )
     377                 : 
     378                 : {
     379                 : /* -------------------------------------------------------------------- */
     380                 : /*      Validate arguments.                                             */
     381                 : /* -------------------------------------------------------------------- */
     382                 :     CPLAssert( pImage != NULL );
     383                 :     
     384             179 :     if( !InitBlockInfo() )
     385               0 :         return CE_Failure;
     386                 :         
     387             179 :     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             179 :     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             179 :     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               0 : CPLErr CPL_STDCALL GDALReadBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
     424                 :                       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               0 : CPLErr GDALRasterBand::WriteBlock( int nXBlockOff, int nYBlockOff,
     479                 :                                    void * pImage )
     480                 : 
     481                 : {
     482                 : /* -------------------------------------------------------------------- */
     483                 : /*      Validate arguments.                                             */
     484                 : /* -------------------------------------------------------------------- */
     485                 :     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               0 : CPLErr CPL_STDCALL GDALWriteBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
     536                 :                        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          589586 : GDALDataType GDALRasterBand::GetRasterDataType()
     558                 : 
     559                 : {
     560          589586 :     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            3356 : GDALDataType CPL_STDCALL GDALGetRasterDataType( GDALRasterBandH hBand )
     574                 : 
     575                 : {
     576            3356 :     VALIDATE_POINTER1( hBand, "GDALGetRasterDataType", GDT_Unknown );
     577                 : 
     578            3356 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
     579            3356 :     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          273156 : void GDALRasterBand::GetBlockSize( int * pnXSize, int *pnYSize )
     607                 : 
     608                 : {
     609          273156 :     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          273156 :         if( pnXSize != NULL )
     621          273156 :             *pnXSize = nBlockXSize;
     622          273156 :         if( pnYSize != NULL )
     623          273156 :             *pnYSize = nBlockYSize;
     624                 :     }
     625          273156 : }
     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             326 : GDALGetBlockSize( GDALRasterBandH hBand, int * pnXSize, int * pnYSize )
     639                 : 
     640                 : {
     641             326 :     VALIDATE_POINTER0( hBand, "GDALGetBlockSize" );
     642                 : 
     643             326 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
     644             326 :     poBand->GetBlockSize( pnXSize, pnYSize );
     645                 : }
     646                 : 
     647                 : /************************************************************************/
     648                 : /*                           InitBlockInfo()                            */
     649                 : /************************************************************************/
     650                 : 
     651         4498278 : int GDALRasterBand::InitBlockInfo()
     652                 : 
     653                 : {
     654         4498278 :     if( papoBlocks != NULL )
     655         4428125 :         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           70153 :     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           70153 :     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           70153 :     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           70153 :     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           70153 :     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           70153 :     nBlocksPerRow = (nRasterXSize+nBlockXSize-1) / nBlockXSize;
     707           70153 :     nBlocksPerColumn = (nRasterYSize+nBlockYSize-1) / nBlockYSize;
     708                 :     
     709           70153 :     if( nBlocksPerRow < SUBBLOCK_SIZE/2 )
     710                 :     {
     711           70119 :         bSubBlockingActive = FALSE;
     712                 : 
     713           70119 :         if (nBlocksPerRow < INT_MAX / nBlocksPerColumn)
     714                 :         {
     715                 :             papoBlocks = (GDALRasterBlock **)
     716           70119 :                 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              34 :         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              34 :         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              34 :         bSubBlockingActive = TRUE;
     743                 : 
     744              34 :         nSubBlocksPerRow = (nBlocksPerRow + SUBBLOCK_SIZE + 1)/SUBBLOCK_SIZE;
     745              34 :         nSubBlocksPerColumn = (nBlocksPerColumn + SUBBLOCK_SIZE + 1)/SUBBLOCK_SIZE;
     746                 : 
     747              34 :         if (nSubBlocksPerRow < INT_MAX / nSubBlocksPerColumn)
     748                 :         {
     749                 :             papoBlocks = (GDALRasterBlock **)
     750              34 :                 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           70153 :     if( papoBlocks == NULL )
     761                 :     {
     762                 :         CPLError( CE_Failure, CPLE_OutOfMemory,
     763               0 :                   "Out of memory in InitBlockInfo()." );
     764               0 :         return FALSE;
     765                 :     }
     766                 : 
     767           70153 :     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          269459 : CPLErr GDALRasterBand::AdoptBlock( int nXBlockOff, int nYBlockOff,
     781                 :                                    GDALRasterBlock * poBlock )
     782                 : 
     783                 : {
     784                 :     int         nBlockIndex;
     785                 :     
     786          269459 :     if( !InitBlockInfo() )
     787               0 :         return CE_Failure;
     788                 :     
     789                 : /* -------------------------------------------------------------------- */
     790                 : /*      Simple case without subblocking.                                */
     791                 : /* -------------------------------------------------------------------- */
     792          269459 :     if( !bSubBlockingActive )
     793                 :     {
     794          265791 :         nBlockIndex = nXBlockOff + nYBlockOff * nBlocksPerRow;
     795                 : 
     796          265791 :         if( papoBlocks[nBlockIndex] == poBlock )
     797               0 :             return( CE_None );
     798                 : 
     799          265791 :         if( papoBlocks[nBlockIndex] != NULL )
     800               0 :             FlushBlock( nXBlockOff, nYBlockOff );
     801                 : 
     802          265791 :         papoBlocks[nBlockIndex] = poBlock;
     803          265791 :         poBlock->Touch();
     804                 : 
     805          265791 :         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            3668 :         + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
     814                 : 
     815            3668 :     if( papoBlocks[nSubBlock] == NULL )
     816                 :     {
     817                 :         int nSubGridSize = 
     818              68 :             sizeof(GDALRasterBlock*) * SUBBLOCK_SIZE * SUBBLOCK_SIZE;
     819                 : 
     820              68 :         papoBlocks[nSubBlock] = (GDALRasterBlock *) VSIMalloc(nSubGridSize);
     821              68 :         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              68 :         memset( papoBlocks[nSubBlock], 0, nSubGridSize );
     829                 :     }
     830                 : 
     831                 : /* -------------------------------------------------------------------- */
     832                 : /*      Check within subblock.                                          */
     833                 : /* -------------------------------------------------------------------- */
     834                 :     GDALRasterBlock **papoSubBlockGrid = 
     835            3668 :         (GDALRasterBlock **) papoBlocks[nSubBlock];
     836                 : 
     837                 :     int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
     838            3668 :         + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
     839                 : 
     840            3668 :     if( papoSubBlockGrid[nBlockInSubBlock] == poBlock )
     841               0 :         return CE_None;
     842                 : 
     843            3668 :     if( papoSubBlockGrid[nBlockInSubBlock] != NULL )
     844               0 :         FlushBlock( nXBlockOff, nYBlockOff );
     845                 : 
     846            3668 :     papoSubBlockGrid[nBlockInSubBlock] = poBlock;
     847            3668 :     poBlock->Touch();
     848                 : 
     849            3668 :     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         1635096 : CPLErr GDALRasterBand::FlushCache()
     868                 : 
     869                 : {
     870         1635096 :     if (papoBlocks == NULL)
     871         1425315 :         return CE_None;
     872                 : 
     873                 : /* -------------------------------------------------------------------- */
     874                 : /*      Flush all blocks in memory ... this case is without subblocking.*/
     875                 : /* -------------------------------------------------------------------- */
     876          209781 :     if( !bSubBlockingActive )
     877                 :     {
     878         1502403 :         for( int iY = 0; iY < nBlocksPerColumn; iY++ )
     879                 :         {
     880         2603699 :             for( int iX = 0; iX < nBlocksPerRow; iX++ )
     881                 :             {
     882         1311015 :                 if( papoBlocks[iX + iY*nBlocksPerRow] != NULL )
     883                 :                 {
     884                 :                     CPLErr    eErr;
     885                 : 
     886          264954 :                     eErr = FlushBlock( iX, iY );
     887                 : 
     888          264954 :                     if( eErr != CE_None )
     889               0 :                         return eErr;
     890                 :                 }
     891                 :             }
     892                 :         }
     893          209719 :         return CE_None;
     894                 :     }
     895                 : 
     896                 : /* -------------------------------------------------------------------- */
     897                 : /*      With subblocking.  We can short circuit missing subblocks.      */
     898                 : /* -------------------------------------------------------------------- */
     899                 :     int iSBX, iSBY;
     900                 : 
     901             148 :     for( iSBY = 0; iSBY < nSubBlocksPerColumn; iSBY++ )
     902                 :     {
     903             411 :         for( iSBX = 0; iSBX < nSubBlocksPerRow; iSBX++ )
     904                 :         {
     905             325 :             int nSubBlock = iSBX + iSBY * nSubBlocksPerRow;
     906                 :         
     907                 :             GDALRasterBlock **papoSubBlockGrid = 
     908             325 :                 (GDALRasterBlock **) papoBlocks[nSubBlock];
     909                 : 
     910             325 :             if( papoSubBlockGrid == NULL )
     911             257 :                 continue;
     912                 : 
     913            4420 :             for( int iY = 0; iY < SUBBLOCK_SIZE; iY++ )
     914                 :             {
     915          282880 :                 for( int iX = 0; iX < SUBBLOCK_SIZE; iX++ )
     916                 :                 {
     917          278528 :                     if( papoSubBlockGrid[iX + iY * SUBBLOCK_SIZE] != NULL )
     918                 :                     {
     919                 :                         CPLErr eErr;
     920                 : 
     921                 :                         eErr = FlushBlock( iX + iSBX * SUBBLOCK_SIZE, 
     922            3667 :                                            iY + iSBY * SUBBLOCK_SIZE );
     923            3667 :                         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              68 :             papoBlocks[nSubBlock] = NULL;
     932              68 :             CPLFree( papoSubBlockGrid );
     933                 :         }
     934                 :     }
     935                 : 
     936              62 :     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          269459 : CPLErr GDALRasterBand::FlushBlock( int nXBlockOff, int nYBlockOff )
     968                 : 
     969                 : {
     970                 :     int             nBlockIndex;
     971          269459 :     GDALRasterBlock *poBlock = NULL;
     972                 : 
     973          269459 :     if( !papoBlocks )
     974               0 :         return CE_None;
     975                 :     
     976                 : /* -------------------------------------------------------------------- */
     977                 : /*      Validate the request                                            */
     978                 : /* -------------------------------------------------------------------- */
     979          269459 :     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          269459 :     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          269459 :     if( !bSubBlockingActive )
    1003                 :     {
    1004          265791 :         nBlockIndex = nXBlockOff + nYBlockOff * nBlocksPerRow;
    1005                 : 
    1006          265791 :         GDALRasterBlock::SafeLockBlock( papoBlocks + nBlockIndex );
    1007                 : 
    1008          265791 :         poBlock = papoBlocks[nBlockIndex];
    1009          265791 :         papoBlocks[nBlockIndex] = NULL;
    1010                 :     }
    1011                 : 
    1012                 : /* -------------------------------------------------------------------- */
    1013                 : /*      Identify our subblock.                                          */
    1014                 : /* -------------------------------------------------------------------- */
    1015                 :     else
    1016                 :     {
    1017                 :         int nSubBlock = TO_SUBBLOCK(nXBlockOff) 
    1018            3668 :             + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
    1019                 :         
    1020            3668 :         if( papoBlocks[nSubBlock] == NULL )
    1021               0 :             return CE_None;
    1022                 :         
    1023                 : /* -------------------------------------------------------------------- */
    1024                 : /*      Check within subblock.                                          */
    1025                 : /* -------------------------------------------------------------------- */
    1026                 :         GDALRasterBlock **papoSubBlockGrid = 
    1027            3668 :             (GDALRasterBlock **) papoBlocks[nSubBlock];
    1028                 :         
    1029                 :         int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
    1030            3668 :             + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
    1031                 :         
    1032            3668 :         GDALRasterBlock::SafeLockBlock( papoSubBlockGrid + nBlockInSubBlock );
    1033                 : 
    1034            3668 :         poBlock = papoSubBlockGrid[nBlockInSubBlock];
    1035            3668 :         papoSubBlockGrid[nBlockInSubBlock] = NULL;
    1036                 :     }
    1037                 : 
    1038                 : /* -------------------------------------------------------------------- */
    1039                 : /*      Is the target block dirty?  If so we need to write it.          */
    1040                 : /* -------------------------------------------------------------------- */
    1041          269459 :     CPLErr eErr = CE_None;
    1042                 : 
    1043          269459 :     if( poBlock == NULL )
    1044               0 :         return CE_None;
    1045                 : 
    1046          269459 :     poBlock->Detach();
    1047                 : 
    1048          269459 :     if( poBlock->GetDirty() )
    1049           20301 :         eErr = poBlock->Write();
    1050                 : 
    1051                 : /* -------------------------------------------------------------------- */
    1052                 : /*      Deallocate the block;                                           */
    1053                 : /* -------------------------------------------------------------------- */
    1054          269459 :     poBlock->DropLock();
    1055          269459 :     delete poBlock;
    1056                 : 
    1057          269459 :     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         3790380 : GDALRasterBlock *GDALRasterBand::TryGetLockedBlockRef( int nXBlockOff, 
    1085                 :                                                        int nYBlockOff )
    1086                 : 
    1087                 : {
    1088         3790380 :     int             nBlockIndex = 0;
    1089                 :     
    1090         3790380 :     if( !InitBlockInfo() )
    1091               0 :         return( NULL );
    1092                 :     
    1093                 : /* -------------------------------------------------------------------- */
    1094                 : /*      Validate the request                                            */
    1095                 : /* -------------------------------------------------------------------- */
    1096         3790380 :     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         3790380 :     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         3790380 :     if( !bSubBlockingActive )
    1120                 :     {
    1121         2454702 :         nBlockIndex = nXBlockOff + nYBlockOff * nBlocksPerRow;
    1122                 :         
    1123         2454702 :         GDALRasterBlock::SafeLockBlock( papoBlocks + nBlockIndex );
    1124                 : 
    1125         2454702 :         return papoBlocks[nBlockIndex];
    1126                 :     }
    1127                 : 
    1128                 : /* -------------------------------------------------------------------- */
    1129                 : /*      Identify our subblock.                                          */
    1130                 : /* -------------------------------------------------------------------- */
    1131                 :     int nSubBlock = TO_SUBBLOCK(nXBlockOff) 
    1132         1335678 :         + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
    1133                 : 
    1134         1335678 :     if( papoBlocks[nSubBlock] == NULL )
    1135              72 :         return NULL;
    1136                 : 
    1137                 : /* -------------------------------------------------------------------- */
    1138                 : /*      Check within subblock.                                          */
    1139                 : /* -------------------------------------------------------------------- */
    1140                 :     GDALRasterBlock **papoSubBlockGrid = 
    1141         1335606 :         (GDALRasterBlock **) papoBlocks[nSubBlock];
    1142                 : 
    1143                 :     int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
    1144         1335606 :         + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
    1145                 : 
    1146         1335606 :     GDALRasterBlock::SafeLockBlock( papoSubBlockGrid + nBlockInSubBlock );
    1147                 : 
    1148         1335606 :     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         3788891 : GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
    1186                 :                                                      int nYBlockOff,
    1187                 :                                                      int bJustInitialize )
    1188                 : 
    1189                 : {
    1190         3788891 :     GDALRasterBlock *poBlock = NULL;
    1191                 : 
    1192                 : /* -------------------------------------------------------------------- */
    1193                 : /*      Try and fetch from cache.                                       */
    1194                 : /* -------------------------------------------------------------------- */
    1195         3788891 :     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         3788891 :     if( poBlock == NULL )
    1203                 :     {
    1204          269459 :         if( !InitBlockInfo() )
    1205               0 :             return( NULL );
    1206                 : 
    1207                 :     /* -------------------------------------------------------------------- */
    1208                 :     /*      Validate the request                                            */
    1209                 :     /* -------------------------------------------------------------------- */
    1210          269459 :         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          269459 :         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          269459 :         poBlock = new GDALRasterBlock( this, nXBlockOff, nYBlockOff );
    1231                 : 
    1232          269459 :         poBlock->AddLock();
    1233                 : 
    1234                 :         /* allocate data space */
    1235          269459 :         if( poBlock->Internalize() != CE_None )
    1236                 :         {
    1237               0 :             poBlock->DropLock();
    1238               0 :             delete poBlock;
    1239               0 :             return( NULL );
    1240                 :         }
    1241                 : 
    1242          269459 :         if ( AdoptBlock( nXBlockOff, nYBlockOff, poBlock ) != CE_None )
    1243                 :         {
    1244               0 :             poBlock->DropLock();
    1245               0 :             delete poBlock;
    1246               0 :             return( NULL );
    1247                 :         }
    1248                 : 
    1249          522114 :         if( !bJustInitialize
    1250          252655 :          && IReadBlock(nXBlockOff,nYBlockOff,poBlock->GetDataRef()) != CE_None)
    1251                 :         {
    1252              10 :             poBlock->DropLock();
    1253              10 :             FlushBlock( nXBlockOff, nYBlockOff );
    1254                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1255                 :           "IReadBlock failed at X offset %d, Y offset %d",
    1256              10 :           nXBlockOff, nYBlockOff );
    1257              10 :       return( NULL );
    1258                 :         }
    1259                 : 
    1260          269449 :         if( !bJustInitialize )
    1261                 :         {
    1262          252645 :             nBlockReads++;
    1263          252645 :             if( nBlockReads == nBlocksPerRow * nBlocksPerColumn + 1 
    1264                 :                 && nBand == 1 && poDS != NULL )
    1265                 :             {
    1266                 :                 CPLDebug( "GDAL", "Potential thrashing on band %d of %s.",
    1267              44 :                           nBand, poDS->GetDescription() );
    1268                 :             }
    1269                 :         }
    1270                 :     }
    1271                 : 
    1272         3788881 :     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          167980 : 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          167980 :     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          167980 :     if( !InitBlockInfo() )
    1316               0 :         return CE_Failure;
    1317                 : 
    1318                 :     // Allocate the source block
    1319          167980 :     int blockSize = nBlockXSize * nBlockYSize;
    1320          167980 :     int elementSize = GDALGetDataTypeSize(eDataType) / 8;
    1321          167980 :     int blockByteSize = blockSize * elementSize;
    1322          167980 :     unsigned char* srcBlock = (unsigned char*) VSIMalloc(blockByteSize);
    1323          167980 :     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          167980 :     double complexSrc[2] = { dfRealValue, dfImaginaryValue };
    1332          167980 :     GDALCopyWords(complexSrc, GDT_CFloat64, 0, srcBlock, eDataType, 0, 1);
    1333                 : 
    1334                 :     // Copy first element to the rest of the block
    1335        38826273 :     for (unsigned char* blockPtr = srcBlock + elementSize; 
    1336                 :    blockPtr < srcBlock + blockByteSize; blockPtr += elementSize) {
    1337        38658293 :   memcpy(blockPtr, srcBlock, elementSize);
    1338                 :     }
    1339                 : 
    1340                 :     // Write block to block cache
    1341          480527 :     for (int j = 0; j < nBlocksPerColumn; ++j) {
    1342          914094 :   for (int i = 0; i < nBlocksPerRow; ++i) {
    1343          601547 :       GDALRasterBlock* destBlock = GetLockedBlockRef(i, j, TRUE);
    1344          601547 :       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          601547 :             if (destBlock->GetDataRef() == NULL)
    1352                 :             {
    1353               0 :                 destBlock->DropLock();
    1354               0 :                 VSIFree(srcBlock);
    1355               0 :                 return CE_Failure;
    1356                 :             }
    1357          601547 :       memcpy(destBlock->GetDataRef(), srcBlock, blockByteSize);
    1358          601547 :       destBlock->MarkDirty();
    1359          601547 :             destBlock->DropLock();
    1360                 :   }
    1361                 :     }
    1362                 : 
    1363                 :     // Free up the source block
    1364          167980 :     VSIFree(srcBlock);
    1365                 : 
    1366          167980 :     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          167980 : CPLErr CPL_STDCALL GDALFillRaster(GDALRasterBandH hBand, double dfRealValue, 
    1380                 :           double dfImaginaryValue)
    1381                 : {
    1382          167980 :     VALIDATE_POINTER1( hBand, "GDALFillRaster", CE_Failure );
    1383                 :     
    1384          167980 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1385          167980 :     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             341 : GDALAccess GDALRasterBand::GetAccess()
    1401                 : 
    1402                 : {
    1403             341 :     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             338 : GDALAccess CPL_STDCALL GDALGetRasterAccess( GDALRasterBandH hBand )
    1417                 : 
    1418                 : {
    1419             338 :     VALIDATE_POINTER1( hBand, "GDALGetRasterAccess", GA_ReadOnly );
    1420                 : 
    1421             338 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1422             338 :     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               9 : char ** CPL_STDCALL GDALGetRasterCategoryNames( GDALRasterBandH hBand )
    1461                 : 
    1462                 : {
    1463               9 :     VALIDATE_POINTER1( hBand, "GDALGetRasterCategoryNames", NULL );
    1464                 : 
    1465               9 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1466               9 :     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             576 : double GDALRasterBand::GetNoDataValue( int *pbSuccess )
    1539                 : 
    1540                 : {
    1541             576 :     if( pbSuccess != NULL )
    1542             576 :         *pbSuccess = FALSE;
    1543                 :     
    1544             576 :     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             544 : GDALGetRasterNoDataValue( GDALRasterBandH hBand, int *pbSuccess )
    1559                 : 
    1560                 : {
    1561             544 :     VALIDATE_POINTER1( hBand, "GDALGetRasterNoDataValue", 0 );
    1562                 : 
    1563             544 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1564             544 :     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              53 : GDALSetRasterNoDataValue( GDALRasterBandH hBand, double dfValue )
    1608                 : 
    1609                 : {
    1610              53 :     VALIDATE_POINTER1( hBand, "GDALSetRasterNoDataValue", CE_Failure );
    1611                 : 
    1612              53 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1613              53 :     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              57 : double GDALRasterBand::GetMaximum( int *pbSuccess )
    1635                 : 
    1636                 : {
    1637              57 :     const char *pszValue = NULL;
    1638                 :     
    1639              57 :     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              57 :     if( pbSuccess != NULL )
    1648              36 :         *pbSuccess = FALSE;
    1649                 : 
    1650              57 :     switch( eDataType )
    1651                 :     {
    1652                 :       case GDT_Byte:
    1653                 :       {
    1654              37 :         const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
    1655              37 :         if (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"))
    1656               0 :             return 127;
    1657                 :         else
    1658              37 :             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              11 : GDALGetRasterMaximum( GDALRasterBandH hBand, int *pbSuccess )
    1700                 : 
    1701                 : {
    1702              11 :     VALIDATE_POINTER1( hBand, "GDALGetRasterMaximum", 0 );
    1703                 : 
    1704              11 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1705              11 :     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              57 : double GDALRasterBand::GetMinimum( int *pbSuccess )
    1727                 : 
    1728                 : {
    1729              57 :     const char *pszValue = NULL;
    1730                 :     
    1731              57 :     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              57 :     if( pbSuccess != NULL )
    1740              36 :         *pbSuccess = FALSE;
    1741                 : 
    1742              57 :     switch( eDataType )
    1743                 :     {
    1744                 :       case GDT_Byte:
    1745                 :       {
    1746              37 :         const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
    1747              37 :         if (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"))
    1748               0 :             return -128;
    1749                 :         else
    1750              37 :             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              11 : GDALGetRasterMinimum( GDALRasterBandH hBand, int *pbSuccess )
    1788                 : 
    1789                 : {
    1790              11 :     VALIDATE_POINTER1( hBand, "GDALGetRasterMinimum", 0 );
    1791                 : 
    1792              11 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1793              11 :     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              28 : GDALColorInterp GDALRasterBand::GetColorInterpretation()
    1813                 : 
    1814                 : {
    1815              28 :     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             406 : GDALGetRasterColorInterpretation( GDALRasterBandH hBand )
    1830                 : 
    1831                 : {
    1832             406 :     VALIDATE_POINTER1( hBand, "GDALGetRasterColorInterpretation", GCI_Undefined );
    1833                 : 
    1834             406 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1835             406 :     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              13 : CPLErr GDALRasterBand::SetColorInterpretation( GDALColorInterp eColorInterp)
    1851                 : 
    1852                 : {
    1853                 :     (void) eColorInterp;
    1854              13 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    1855                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1856              10 :                   "SetColorInterpretation() not supported for this dataset." );
    1857              13 :     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              43 : GDALSetRasterColorInterpretation( GDALRasterBandH hBand,
    1872                 :                                   GDALColorInterp eColorInterp )
    1873                 : 
    1874                 : {
    1875              43 :     VALIDATE_POINTER1( hBand, "GDALSetRasterColorInterpretation", CE_Failure );
    1876                 : 
    1877              43 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1878              43 :     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              28 : GDALColorTable *GDALRasterBand::GetColorTable()
    1898                 : 
    1899                 : {
    1900              28 :     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             467 : GDALColorTableH CPL_STDCALL GDALGetRasterColorTable( GDALRasterBandH hBand )
    1914                 : 
    1915                 : {
    1916             467 :     VALIDATE_POINTER1( hBand, "GDALGetRasterColorTable", NULL );
    1917                 : 
    1918             467 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1919             467 :     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              15 : GDALSetRasterColorTable( GDALRasterBandH hBand, GDALColorTableH hCT )
    1964                 : 
    1965                 : {
    1966              15 :     VALIDATE_POINTER1( hBand, "GDALSetRasterColorTable", CE_Failure );
    1967                 : 
    1968              15 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    1969              15 :     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              16 : int GDALRasterBand::HasArbitraryOverviews()
    1992                 : 
    1993                 : {
    1994              16 :     return FALSE;
    1995                 : }
    1996                 : 
    1997                 : /************************************************************************/
    1998                 : /*                     GDALHasArbitraryOverviews()                      */
    1999                 : /************************************************************************/
    2000                 : 
    2001                 : /**
    2002                 :  * \brief Check for arbitrary overviews.
    2003                 :  *
    2004                 :  * @see GDALRasterBand::HasArbitraryOverviews()
    2005                 :  */
    2006                 : 
    2007               9 : int CPL_STDCALL GDALHasArbitraryOverviews( GDALRasterBandH hBand )
    2008                 : 
    2009                 : {
    2010               9 :     VALIDATE_POINTER1( hBand, "GDALHasArbitraryOverviews", 0 );
    2011                 :     
    2012               9 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2013               9 :     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          299275 : int GDALRasterBand::GetOverviewCount()
    2029                 : 
    2030                 : {
    2031          299275 :     if( poDS != NULL && poDS->oOvManager.IsInitialized() )
    2032             459 :         return poDS->oOvManager.GetOverviewCount( nBand );
    2033                 :     else
    2034          298816 :         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              67 : int CPL_STDCALL GDALGetOverviewCount( GDALRasterBandH hBand )
    2048                 : 
    2049                 : {
    2050              67 :     VALIDATE_POINTER1( hBand, "GDALGetOverviewCount", 0 );
    2051                 : 
    2052              67 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2053              67 :     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             202 : GDALRasterBand * GDALRasterBand::GetOverview( int i )
    2072                 : 
    2073                 : {
    2074             202 :     if( poDS != NULL && poDS->oOvManager.IsInitialized() )
    2075             202 :         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             178 : GDALRasterBandH CPL_STDCALL GDALGetOverview( GDALRasterBandH hBand, int i )
    2091                 : 
    2092                 : {
    2093             178 :     VALIDATE_POINTER1( hBand, "GDALGetOverview", NULL );
    2094                 : 
    2095             178 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2096             178 :     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               4 : GDALRasterBand *GDALRasterBand::GetRasterSampleOverview( int nDesiredSamples )
    2121                 : 
    2122                 : {
    2123               4 :     double dfBestSamples = 0; 
    2124               4 :     GDALRasterBand *poBestBand = this;
    2125                 : 
    2126               4 :     dfBestSamples = GetXSize() * (double)GetYSize();
    2127                 : 
    2128              22 :     for( int iOverview = 0; iOverview < GetOverviewCount(); iOverview++ )
    2129                 :     {
    2130              18 :         GDALRasterBand  *poOBand = GetOverview( iOverview );
    2131              18 :         double          dfOSamples = 0;
    2132                 : 
    2133              18 :         dfOSamples = poOBand->GetXSize() * (double)poOBand->GetYSize();
    2134                 : 
    2135              18 :         if( dfOSamples < dfBestSamples && dfOSamples > nDesiredSamples )
    2136                 :         {
    2137              12 :             dfBestSamples = dfOSamples;
    2138              12 :             poBestBand = poOBand;
    2139                 :         }
    2140                 :     }
    2141                 : 
    2142               4 :     return poBestBand;
    2143                 : }
    2144                 : 
    2145                 : /************************************************************************/
    2146                 : /*                    GDALGetRasterSampleOverview()                     */
    2147                 : /************************************************************************/
    2148                 : 
    2149                 : /**
    2150                 :  * \brief Fetch best sampling overview.
    2151                 :  *
    2152                 :  * @see GDALRasterBand::GetRasterSampleOverview()
    2153                 :  */
    2154                 : 
    2155                 : GDALRasterBandH CPL_STDCALL 
    2156               0 : GDALGetRasterSampleOverview( GDALRasterBandH hBand, int nDesiredSamples )
    2157                 : 
    2158                 : {
    2159               0 :     VALIDATE_POINTER1( hBand, "GDALGetRasterSampleOverview", NULL );
    2160                 : 
    2161               0 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2162                 :     return (GDALRasterBandH)
    2163               0 :         poBand->GetRasterSampleOverview( nDesiredSamples );
    2164                 : }
    2165                 : 
    2166                 : /************************************************************************/
    2167                 : /*                           BuildOverviews()                           */
    2168                 : /************************************************************************/
    2169                 : 
    2170                 : /**
    2171                 :  * \brief Build raster overview(s)
    2172                 :  *
    2173                 :  * If the operation is unsupported for the indicated dataset, then 
    2174                 :  * CE_Failure is returned, and CPLGetLastErrorNo() will return 
    2175                 :  * CPLE_NotSupported.
    2176                 :  *
    2177                 :  * WARNING:  It is not possible to build overviews for a single band in
    2178                 :  * TIFF format, and thus this method does not work for TIFF format, or any
    2179                 :  * formats that use the default overview building in TIFF format.  Instead
    2180                 :  * it is necessary to build overviews on the dataset as a whole using
    2181                 :  * GDALDataset::BuildOverviews().  That makes this method pretty useless
    2182                 :  * from a practical point of view. 
    2183                 :  *
    2184                 :  * @param pszResampling one of "NEAREST", "GAUSS", "CUBIC", "AVERAGE", "MODE",
    2185                 :  * "AVERAGE_MAGPHASE" or "NONE" controlling the downsampling method applied.
    2186                 :  * @param nOverviews number of overviews to build. 
    2187                 :  * @param panOverviewList the list of overview decimation factors to build. 
    2188                 :  * @param pfnProgress a function to call to report progress, or NULL.
    2189                 :  * @param pProgressData application data to pass to the progress function.
    2190                 :  *
    2191                 :  * @return CE_None on success or CE_Failure if the operation doesn't work. 
    2192                 :  */
    2193                 : 
    2194               0 : CPLErr GDALRasterBand::BuildOverviews( const char * pszResampling, 
    2195                 :                                        int nOverviews, 
    2196                 :                                        int * panOverviewList, 
    2197                 :                                        GDALProgressFunc pfnProgress, 
    2198                 :                                        void * pProgressData )
    2199                 : 
    2200                 : {
    2201                 :     (void) pszResampling;
    2202                 :     (void) nOverviews;
    2203                 :     (void) panOverviewList;
    2204                 :     (void) pfnProgress;
    2205                 :     (void) pProgressData;
    2206                 : 
    2207                 :     CPLError( CE_Failure, CPLE_NotSupported,
    2208               0 :               "BuildOverviews() not supported for this dataset." );
    2209                 :     
    2210               0 :     return( CE_Failure );
    2211                 : }
    2212                 : 
    2213                 : /************************************************************************/
    2214                 : /*                             GetOffset()                              */
    2215                 : /************************************************************************/
    2216                 : 
    2217                 : /**
    2218                 :  * \brief Fetch the raster value offset.
    2219                 :  *
    2220                 :  * This value (in combination with the GetScale() value) is used to
    2221                 :  * transform raw pixel values into the units returned by GetUnits().  
    2222                 :  * For example this might be used to store elevations in GUInt16 bands
    2223                 :  * with a precision of 0.1, and starting from -100. 
    2224                 :  * 
    2225                 :  * Units value = (raw value * scale) + offset
    2226                 :  * 
    2227                 :  * For file formats that don't know this intrinsically a value of zero
    2228                 :  * is returned. 
    2229                 :  *
    2230                 :  * This method is the same as the C function GDALGetRasterOffset().
    2231                 :  *
    2232                 :  * @param pbSuccess pointer to a boolean to use to indicate if the
    2233                 :  * returned value is meaningful or not.  May be NULL (default).
    2234                 :  *
    2235                 :  * @return the raster offset.
    2236                 :  */
    2237                 : 
    2238              36 : double GDALRasterBand::GetOffset( int *pbSuccess )
    2239                 : 
    2240                 : {
    2241              36 :     if( pbSuccess != NULL )
    2242              34 :         *pbSuccess = FALSE;
    2243                 : 
    2244              36 :     return 0.0;
    2245                 : }
    2246                 : 
    2247                 : /************************************************************************/
    2248                 : /*                        GDALGetRasterOffset()                         */
    2249                 : /************************************************************************/
    2250                 : 
    2251                 : /**
    2252                 :  * \brief Fetch the raster value offset.
    2253                 :  *
    2254                 :  * @see GDALRasterBand::GetOffset()
    2255                 :  */
    2256                 : 
    2257              10 : double CPL_STDCALL GDALGetRasterOffset( GDALRasterBandH hBand, int *pbSuccess )
    2258                 : 
    2259                 : {
    2260              10 :     VALIDATE_POINTER1( hBand, "GDALGetRasterOffset", 0 );
    2261                 : 
    2262              10 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2263              10 :     return poBand->GetOffset( pbSuccess );
    2264                 : }
    2265                 : 
    2266                 : /************************************************************************/
    2267                 : /*                             SetOffset()                              */
    2268                 : /************************************************************************/
    2269                 : 
    2270                 : /**
    2271                 :  * \brief Set scaling offset.
    2272                 :  *
    2273                 :  * Very few formats implement this method.   When not implemented it will
    2274                 :  * issue a CPLE_NotSupported error and return CE_Failure. 
    2275                 :  * 
    2276                 :  * @param dfNewOffset the new offset.
    2277                 :  *
    2278                 :  * @return CE_None or success or CE_Failure on failure. 
    2279                 :  */
    2280                 : 
    2281               0 : CPLErr GDALRasterBand::SetOffset( double dfNewOffset )
    2282                 : 
    2283                 : {
    2284               0 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    2285                 :         CPLError( CE_Failure, CPLE_NotSupported,
    2286               0 :                   "SetOffset() not supported on this raster band." );
    2287                 :     
    2288               0 :     return CE_Failure;
    2289                 : }
    2290                 : 
    2291                 : /************************************************************************/
    2292                 : /*                        GDALSetRasterOffset()                         */
    2293                 : /************************************************************************/
    2294                 : 
    2295                 : /**
    2296                 :  * \brief Set scaling offset.
    2297                 :  *
    2298                 :  * @see GDALRasterBand::SetOffset()
    2299                 :  */
    2300                 : 
    2301                 : CPLErr CPL_STDCALL 
    2302               0 : GDALSetRasterOffset( GDALRasterBandH hBand, double dfNewOffset )
    2303                 : 
    2304                 : {
    2305               0 :     VALIDATE_POINTER1( hBand, "GDALSetRasterOffset", CE_Failure );
    2306                 : 
    2307               0 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2308               0 :     return poBand->SetOffset( dfNewOffset );
    2309                 : }
    2310                 : 
    2311                 : /************************************************************************/
    2312                 : /*                              GetScale()                              */
    2313                 : /************************************************************************/
    2314                 : 
    2315                 : /**
    2316                 :  * \brief Fetch the raster value scale.
    2317                 :  *
    2318                 :  * This value (in combination with the GetOffset() value) is used to
    2319                 :  * transform raw pixel values into the units returned by GetUnits().  
    2320                 :  * For example this might be used to store elevations in GUInt16 bands
    2321                 :  * with a precision of 0.1, and starting from -100. 
    2322                 :  * 
    2323                 :  * Units value = (raw value * scale) + offset
    2324                 :  * 
    2325                 :  * For file formats that don't know this intrinsically a value of one
    2326                 :  * is returned. 
    2327                 :  *
    2328                 :  * This method is the same as the C function GDALGetRasterScale().
    2329                 :  *
    2330                 :  * @param pbSuccess pointer to a boolean to use to indicate if the
    2331                 :  * returned value is meaningful or not.  May be NULL (default).
    2332                 :  *
    2333                 :  * @return the raster scale.
    2334                 :  */
    2335                 : 
    2336              36 : double GDALRasterBand::GetScale( int *pbSuccess )
    2337                 : 
    2338                 : {
    2339              36 :     if( pbSuccess != NULL )
    2340              34 :         *pbSuccess = FALSE;
    2341                 : 
    2342              36 :     return 1.0;
    2343                 : }
    2344                 : 
    2345                 : /************************************************************************/
    2346                 : /*                         GDALGetRasterScale()                         */
    2347                 : /************************************************************************/
    2348                 : 
    2349                 : /**
    2350                 :  * \brief Fetch the raster value scale.
    2351                 :  *
    2352                 :  * @see GDALRasterBand::GetScale()
    2353                 :  */
    2354                 : 
    2355              10 : double CPL_STDCALL GDALGetRasterScale( GDALRasterBandH hBand, int *pbSuccess )
    2356                 : 
    2357                 : {
    2358              10 :     VALIDATE_POINTER1( hBand, "GDALGetRasterScale", 0 );
    2359                 : 
    2360              10 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2361              10 :     return poBand->GetScale( pbSuccess );
    2362                 : }
    2363                 : 
    2364                 : /************************************************************************/
    2365                 : /*                              SetScale()                              */
    2366                 : /************************************************************************/
    2367                 : 
    2368                 : /**
    2369                 :  * \brief Set scaling ratio.
    2370                 :  *
    2371                 :  * Very few formats implement this method.   When not implemented it will
    2372                 :  * issue a CPLE_NotSupported error and return CE_Failure. 
    2373                 :  * 
    2374                 :  * @param dfNewScale the new scale.
    2375                 :  *
    2376                 :  * @return CE_None or success or CE_Failure on failure. 
    2377                 :  */
    2378                 : 
    2379               0 : CPLErr GDALRasterBand::SetScale( double dfNewScale )
    2380                 : 
    2381                 : {
    2382               0 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    2383                 :         CPLError( CE_Failure, CPLE_NotSupported,
    2384               0 :                   "SetScale() not supported on this raster band." );
    2385                 :     
    2386               0 :     return CE_Failure;
    2387                 : }
    2388                 : 
    2389                 : /************************************************************************/
    2390                 : /*                        GDALSetRasterScale()                          */
    2391                 : /************************************************************************/
    2392                 : 
    2393                 : /**
    2394                 :  * \brief Set scaling ratio.
    2395                 :  *
    2396                 :  * @see GDALRasterBand::SetScale()
    2397                 :  */
    2398                 : 
    2399                 : CPLErr CPL_STDCALL 
    2400               0 : GDALSetRasterScale( GDALRasterBandH hBand, double dfNewOffset )
    2401                 : 
    2402                 : {
    2403               0 :     VALIDATE_POINTER1( hBand, "GDALSetRasterScale", CE_Failure );
    2404                 : 
    2405               0 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2406               0 :     return poBand->SetScale( dfNewOffset );
    2407                 : }
    2408                 : 
    2409                 : /************************************************************************/
    2410                 : /*                            GetUnitType()                             */
    2411                 : /************************************************************************/
    2412                 : 
    2413                 : /**
    2414                 :  * \brief Return raster unit type.
    2415                 :  *
    2416                 :  * Return a name for the units of this raster's values.  For instance, it
    2417                 :  * might be "m" for an elevation model in meters, or "ft" for feet.  If no 
    2418                 :  * units are available, a value of "" will be returned.  The returned string 
    2419                 :  * should not be modified, nor freed by the calling application.
    2420                 :  *
    2421                 :  * This method is the same as the C function GDALGetRasterUnitType(). 
    2422                 :  *
    2423                 :  * @return unit name string.
    2424                 :  */
    2425                 : 
    2426              17 : const char *GDALRasterBand::GetUnitType()
    2427                 : 
    2428                 : {
    2429              17 :     return "";
    2430                 : }
    2431                 : 
    2432                 : /************************************************************************/
    2433                 : /*                       GDALGetRasterUnitType()                        */
    2434                 : /************************************************************************/
    2435                 : 
    2436                 : /**
    2437                 :  * \brief Return raster unit type.
    2438                 :  *
    2439                 :  * @see GDALRasterBand::GetUnitType()
    2440                 :  */
    2441                 : 
    2442               9 : const char * CPL_STDCALL GDALGetRasterUnitType( GDALRasterBandH hBand )
    2443                 : 
    2444                 : {
    2445               9 :     VALIDATE_POINTER1( hBand, "GDALGetRasterUnitType", NULL );
    2446                 : 
    2447               9 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2448               9 :     return poBand->GetUnitType();
    2449                 : }
    2450                 : 
    2451                 : /************************************************************************/
    2452                 : /*                            SetUnitType()                             */
    2453                 : /************************************************************************/
    2454                 : 
    2455                 : /**
    2456                 :  * \brief Set unit type.
    2457                 :  *
    2458                 :  * Set the unit type for a raster band.  Values should be one of
    2459                 :  * "" (the default indicating it is unknown), "m" indicating meters, 
    2460                 :  * or "ft" indicating feet, though other nonstandard values are allowed.
    2461                 :  *
    2462                 :  * @param pszNewValue the new unit type value.
    2463                 :  *
    2464                 :  * @return CE_None on success or CE_Failure if not succuessful, or 
    2465                 :  * unsupported.
    2466                 :  */
    2467                 : 
    2468               0 : CPLErr GDALRasterBand::SetUnitType( const char *pszNewValue )
    2469                 : 
    2470                 : {
    2471               0 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    2472                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    2473               0 :                   "SetUnitType() not supported on this raster band." );
    2474               0 :     return CE_Failure;
    2475                 : }
    2476                 : 
    2477                 : /************************************************************************/
    2478                 : /*                              GetXSize()                              */
    2479                 : /************************************************************************/
    2480                 : 
    2481                 : /**
    2482                 :  * \brief Fetch XSize of raster. 
    2483                 :  *
    2484                 :  * This method is the same as the C function GDALGetRasterBandXSize(). 
    2485                 :  *
    2486                 :  * @return the width in pixels of this band.
    2487                 :  */
    2488                 : 
    2489          519478 : int GDALRasterBand::GetXSize()
    2490                 : 
    2491                 : {
    2492          519478 :     return nRasterXSize;
    2493                 : }
    2494                 : 
    2495                 : /************************************************************************/
    2496                 : /*                       GDALGetRasterBandXSize()                       */
    2497                 : /************************************************************************/
    2498                 : 
    2499                 : /**
    2500                 :  * \brief Fetch XSize of raster. 
    2501                 :  *
    2502                 :  * @see GDALRasterBand::GetXSize()
    2503                 :  */
    2504                 : 
    2505            1781 : int CPL_STDCALL GDALGetRasterBandXSize( GDALRasterBandH hBand )
    2506                 : 
    2507                 : {
    2508            1781 :     VALIDATE_POINTER1( hBand, "GDALGetRasterBandXSize", 0 );
    2509                 : 
    2510            1781 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2511            1781 :     return poBand->GetXSize();
    2512                 : }
    2513                 : 
    2514                 : /************************************************************************/
    2515                 : /*                              GetYSize()                              */
    2516                 : /************************************************************************/
    2517                 : 
    2518                 : /**
    2519                 :  * \brief Fetch YSize of raster. 
    2520                 :  *
    2521                 :  * This method is the same as the C function GDALGetRasterBandYSize(). 
    2522                 :  *
    2523                 :  * @return the height in pixels of this band.
    2524                 :  */
    2525                 : 
    2526          110972 : int GDALRasterBand::GetYSize()
    2527                 : 
    2528                 : {
    2529          110972 :     return nRasterYSize;
    2530                 : }
    2531                 : 
    2532                 : /************************************************************************/
    2533                 : /*                       GDALGetRasterBandYSize()                       */
    2534                 : /************************************************************************/
    2535                 : 
    2536                 : /**
    2537                 :  * \brief Fetch YSize of raster. 
    2538                 :  *
    2539                 :  * @see GDALRasterBand::GetYSize()
    2540                 :  */
    2541                 : 
    2542            1771 : int CPL_STDCALL GDALGetRasterBandYSize( GDALRasterBandH hBand )
    2543                 : 
    2544                 : {
    2545            1771 :     VALIDATE_POINTER1( hBand, "GDALGetRasterBandYSize", 0 );
    2546                 : 
    2547            1771 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2548            1771 :     return poBand->GetYSize();
    2549                 : }
    2550                 : 
    2551                 : /************************************************************************/
    2552                 : /*                              GetBand()                               */
    2553                 : /************************************************************************/
    2554                 : 
    2555                 : /**
    2556                 :  * \brief Fetch the band number.
    2557                 :  *
    2558                 :  * This method returns the band that this GDALRasterBand objects represents
    2559                 :  * within it's dataset.  This method may return a value of 0 to indicate
    2560                 :  * GDALRasterBand objects without an apparently relationship to a dataset,
    2561                 :  * such as GDALRasterBands serving as overviews.
    2562                 :  *
    2563                 :  * This method is the same as the C function GDALGetBandNumber().
    2564                 :  *
    2565                 :  * @return band number (1+) or 0 if the band number isn't known.
    2566                 :  */
    2567                 : 
    2568            1711 : int GDALRasterBand::GetBand()
    2569                 : 
    2570                 : {
    2571            1711 :     return nBand;
    2572                 : }
    2573                 : 
    2574                 : /************************************************************************/
    2575                 : /*                         GDALGetBandNumber()                          */
    2576                 : /************************************************************************/
    2577                 : 
    2578                 : /**
    2579                 :  * \brief Fetch the band number.
    2580                 :  *
    2581                 :  * @see GDALRasterBand::GetBand()
    2582                 :  */
    2583                 : 
    2584               0 : int CPL_STDCALL GDALGetBandNumber( GDALRasterBandH hBand )
    2585                 : 
    2586                 : {
    2587               0 :     VALIDATE_POINTER1( hBand, "GDALGetBandNumber", 0 );
    2588                 : 
    2589               0 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2590               0 :     return poBand->GetBand();
    2591                 : }
    2592                 : 
    2593                 : /************************************************************************/
    2594                 : /*                             GetDataset()                             */
    2595                 : /************************************************************************/
    2596                 : 
    2597                 : /**
    2598                 :  * \brief Fetch the owning dataset handle.
    2599                 :  *
    2600                 :  * Note that some GDALRasterBands are not considered to be a part of a dataset,
    2601                 :  * such as overviews or other "freestanding" bands. 
    2602                 :  *
    2603                 :  * This method is the same as the C function GDALGetBandDataset()
    2604                 :  *
    2605                 :  * @return the pointer to the GDALDataset to which this band belongs, or
    2606                 :  * NULL if this cannot be determined.
    2607                 :  */
    2608                 : 
    2609          483839 : GDALDataset *GDALRasterBand::GetDataset()
    2610                 : 
    2611                 : {
    2612          483839 :     return poDS;
    2613                 : }
    2614                 : 
    2615                 : /************************************************************************/
    2616                 : /*                         GDALGetBandDataset()                         */
    2617                 : /************************************************************************/
    2618                 : 
    2619                 : /**
    2620                 :  * \brief Fetch the owning dataset handle.
    2621                 :  *
    2622                 :  * @see GDALRasterBand::GetDataset()
    2623                 :  */
    2624                 : 
    2625               7 : GDALDatasetH CPL_STDCALL GDALGetBandDataset( GDALRasterBandH hBand )
    2626                 : 
    2627                 : {
    2628               7 :     VALIDATE_POINTER1( hBand, "GDALGetBandDataset", NULL );
    2629                 : 
    2630               7 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    2631               7 :     return (GDALDatasetH) poBand->GetDataset();
    2632                 : }
    2633                 : 
    2634                 : /************************************************************************/
    2635                 : /*                            GetHistogram()                            */
    2636                 : /************************************************************************/
    2637                 : 
    2638                 : /**
    2639                 :  * \brief Compute raster histogram. 
    2640                 :  *
    2641                 :  * Note that the bucket size is (dfMax-dfMin) / nBuckets.  
    2642                 :  *
    2643                 :  * For example to compute a simple 256 entry histogram of eight bit data, 
    2644                 :  * the following would be suitable.  The unusual bounds are to ensure that
    2645                 :  * bucket boundaries don't fall right on integer values causing possible errors
    2646                 :  * due to rounding after scaling. 
    2647                 : <pre>
    2648                 :     int anHistogram[256];
    2649                 : 
    2650                 :     poBand->GetHistogram( -0.5, 255.5, 256, anHistogram, FALSE, FALSE, 
    2651                 :                           GDALDummyProgress, NULL );
    2652                 : </pre>
    2653                 :  *
    2654                 :  * Note that setting bApproxOK will generally result in a subsampling of the
    2655                 :  * file, and will utilize overviews if available.  It should generally 
    2656                 :  * produce a representative histogram for the data that is suitable for use
    2657                 :  * in generating histogram based luts for instance.  Generally bApproxOK is
    2658                 :  * much faster than an exactly computed histogram.
    2659                 :  *
    2660                 :  * @param dfMin the lower bound of the histogram.
    2661                 :  * @param dfMax the upper bound of the histogram.
    2662                 :  * @param nBuckets the number of buckets in panHistogram.
    2663                 :  * @param panHistogram array into which the histogram totals are placed.
    2664                 :  * @param bIncludeOutOfRange if TRUE values below the histogram range will
    2665                 :  * mapped into panHistogram[0], and values above will be mapped into 
    2666                 :  * panHistogram[nBuckets-1] otherwise out of range values are discarded.
    2667                 :  * @param bApproxOK TRUE if an approximate, or incomplete histogram OK.
    2668                 :  * @param pfnProgress function to report progress to completion. 
    2669                 :  * @param pProgressData application data to pass to pfnProgress. 
    2670                 :  *
    2671                 :  * @return CE_None on success, or CE_Failure if something goes wrong. 
    2672                 :  */
    2673                 : 
    2674               4 : CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax, 
    2675                 :                                      int nBuckets, int *panHistogram, 
    2676                 :                                      int bIncludeOutOfRange, int bApproxOK,
    2677                 :                                      GDALProgressFunc pfnProgress, 
    2678                 :                                      void *pProgressData )
    2679                 : 
    2680                 : {
    2681                 :     CPLAssert( NULL != panHistogram );
    2682                 : 
    2683               4 :     if( pfnProgress == NULL )
    2684               4 :         pfnProgress = GDALDummyProgress;
    2685                 : 
    2686                 : /* -------------------------------------------------------------------- */
    2687                 : /*      If we have overviews, use them for the histogram.               */
    2688                 : /* -------------------------------------------------------------------- */
    2689               4 :     if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
    2690                 :     {
    2691                 :         // FIXME: should we use the most reduced overview here or use some
    2692                 :         // minimum number of samples like GDALRasterBand::ComputeStatistics()
    2693                 :         // does?
    2694               0 :         GDALRasterBand *poBestOverview = GetRasterSampleOverview( 0 );
    2695                 :         
    2696               0 :         if( poBestOverview != this )
    2697                 :         {
    2698                 :             return poBestOverview->GetHistogram( dfMin, dfMax, nBuckets,
    2699                 :                                                  panHistogram,
    2700                 :                                                  bIncludeOutOfRange, bApproxOK,
    2701               0 :                                                  pfnProgress, pProgressData );
    2702                 :         }
    2703                 :     }
    2704                 : 
    2705                 : /* -------------------------------------------------------------------- */
    2706                 : /*      Read actual data and build histogram.                           */
    2707                 : /* -------------------------------------------------------------------- */
    2708                 :     double      dfScale;
    2709                 : 
    2710               4 :     if( !pfnProgress( 0.0, "Compute Histogram", pProgressData ) )
    2711                 :     {
    2712               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    2713               0 :         return CE_Failure;
    2714                 :     }
    2715                 : 
    2716               4 :     dfScale = nBuckets / (dfMax - dfMin);
    2717               4 :     memset( panHistogram, 0, sizeof(int) * nBuckets );
    2718                 : 
    2719               4 :     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
    2720               4 :     int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
    2721                 : 
    2722               4 :     if ( bApproxOK && HasArbitraryOverviews() )
    2723                 :     {
    2724                 : /* -------------------------------------------------------------------- */
    2725                 : /*      Figure out how much the image should be reduced to get an       */
    2726                 : /*      approximate value.                                              */
    2727                 : /* -------------------------------------------------------------------- */
    2728                 :         void    *pData;
    2729                 :         int     nXReduced, nYReduced;
    2730                 :         double  dfReduction = sqrt(
    2731               0 :             (double)nRasterXSize * nRasterYSize / GDALSTAT_APPROX_NUMSAMPLES );
    2732                 : 
    2733               0 :         if ( dfReduction > 1.0 )
    2734                 :         {
    2735               0 :             nXReduced = (int)( nRasterXSize / dfReduction );
    2736               0 :             nYReduced = (int)( nRasterYSize / dfReduction );
    2737                 : 
    2738                 :             // Catch the case of huge resizing ratios here
    2739               0 :             if ( nXReduced == 0 )
    2740               0 :                 nXReduced = 1;
    2741               0 :             if ( nYReduced == 0 )
    2742               0 :                 nYReduced = 1;
    2743                 :         }
    2744                 :         else
    2745                 :         {
    2746               0 :             nXReduced = nRasterXSize;
    2747               0 :             nYReduced = nRasterYSize;
    2748                 :         }
    2749                 : 
    2750                 :         pData =
    2751               0 :             CPLMalloc(GDALGetDataTypeSize(eDataType)/8 * nXReduced * nYReduced);
    2752                 : 
    2753                 :         CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
    2754               0 :                    nXReduced, nYReduced, eDataType, 0, 0 );
    2755               0 :         if ( eErr != CE_None )
    2756                 :         {
    2757               0 :             CPLFree(pData);
    2758               0 :             return eErr;
    2759                 :         }
    2760                 :         
    2761                 :         /* this isn't the fastest way to do this, but is easier for now */
    2762               0 :         for( int iY = 0; iY < nYReduced; iY++ )
    2763                 :         {
    2764               0 :             for( int iX = 0; iX < nXReduced; iX++ )
    2765                 :             {
    2766               0 :                 int    iOffset = iX + iY * nXReduced;
    2767                 :                 int    nIndex;
    2768               0 :                 double dfValue = 0.0;
    2769                 : 
    2770               0 :                 switch( eDataType )
    2771                 :                 {
    2772                 :                   case GDT_Byte:
    2773                 :                   {
    2774               0 :                     if (bSignedByte)
    2775               0 :                         dfValue = ((signed char *)pData)[iOffset];
    2776                 :                     else
    2777               0 :                         dfValue = ((GByte *)pData)[iOffset];
    2778               0 :                     break;
    2779                 :                   }
    2780                 :                   case GDT_UInt16:
    2781               0 :                     dfValue = ((GUInt16 *)pData)[iOffset];
    2782               0 :                     break;
    2783                 :                   case GDT_Int16:
    2784               0 :                     dfValue = ((GInt16 *)pData)[iOffset];
    2785               0 :                     break;
    2786                 :                   case GDT_UInt32:
    2787               0 :                     dfValue = ((GUInt32 *)pData)[iOffset];
    2788               0 :                     break;
    2789                 :                   case GDT_Int32:
    2790               0 :                     dfValue = ((GInt32 *)pData)[iOffset];
    2791               0 :                     break;
    2792                 :                   case GDT_Float32:
    2793               0 :                     dfValue = ((float *)pData)[iOffset];
    2794               0 :                     if (CPLIsNan(dfValue))
    2795               0 :                         continue;
    2796               0 :                     break;
    2797                 :                   case GDT_Float64:
    2798               0 :                     dfValue = ((double *)pData)[iOffset];
    2799               0 :                     if (CPLIsNan(dfValue))
    2800               0 :                         continue;
    2801               0 :                     break;
    2802                 :                   case GDT_CInt16:
    2803                 :                     {
    2804               0 :                         double dfReal = ((GInt16 *)pData)[iOffset*2];
    2805               0 :                         double dfImag = ((GInt16 *)pData)[iOffset*2+1];
    2806               0 :                         if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
    2807               0 :                             continue;
    2808               0 :                         dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    2809                 :                     }
    2810               0 :                     break;
    2811                 :                   case GDT_CInt32:
    2812                 :                     {
    2813               0 :                         double dfReal = ((GInt32 *)pData)[iOffset*2];
    2814               0 :                         double dfImag = ((GInt32 *)pData)[iOffset*2+1];
    2815               0 :                         if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
    2816               0 :                             continue;
    2817               0 :                         dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    2818                 :                     }
    2819               0 :                     break;
    2820                 :                   case GDT_CFloat32:
    2821                 :                     {
    2822               0 :                         double dfReal = ((float *)pData)[iOffset*2];
    2823               0 :                         double dfImag = ((float *)pData)[iOffset*2+1];
    2824               0 :                         if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
    2825               0 :                             continue;
    2826               0 :                         dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    2827                 :                     }
    2828               0 :                     break;
    2829                 :                   case GDT_CFloat64:
    2830                 :                     {
    2831               0 :                         double dfReal = ((double *)pData)[iOffset*2];
    2832               0 :                         double dfImag = ((double *)pData)[iOffset*2+1];
    2833               0 :                         if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
    2834               0 :                             continue;
    2835               0 :                         dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    2836                 :                     }
    2837                 :                     break;
    2838                 :                   default:
    2839                 :                     CPLAssert( FALSE );
    2840                 :                 }
    2841                 : 
    2842               0 :                 nIndex = (int) floor((dfValue - dfMin) * dfScale);
    2843                 :                 
    2844               0 :                 if( nIndex < 0 )
    2845                 :                 {
    2846               0 :                     if( bIncludeOutOfRange )
    2847               0 :                         panHistogram[0]++;
    2848                 :                 }
    2849               0 :                 else if( nIndex >= nBuckets )
    2850                 :                 {
    2851               0 :                     if( bIncludeOutOfRange )
    2852               0 :                         panHistogram[nBuckets-1]++;
    2853                 :                 }
    2854                 :                 else
    2855                 :                 {
    2856               0 :                     panHistogram[nIndex]++;
    2857                 :                 }
    2858                 :             }
    2859                 :         }
    2860                 : 
    2861               0 :         CPLFree( pData );
    2862                 :     }
    2863                 : 
    2864                 :     else    // No arbitrary overviews
    2865                 :     {
    2866                 :         int         nSampleRate;
    2867                 : 
    2868               4 :         if( !InitBlockInfo() )
    2869               0 :             return CE_Failure;
    2870                 :     
    2871                 : /* -------------------------------------------------------------------- */
    2872                 : /*      Figure out the ratio of blocks we will read to get an           */
    2873                 : /*      approximate value.                                              */
    2874                 : /* -------------------------------------------------------------------- */
    2875                 : 
    2876               4 :         if ( bApproxOK )
    2877                 :         {
    2878                 :             nSampleRate = 
    2879               2 :                 (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn));
    2880                 :         }
    2881                 :         else
    2882               2 :             nSampleRate = 1;
    2883                 :     
    2884                 : /* -------------------------------------------------------------------- */
    2885                 : /*      Read the blocks, and add to histogram.                          */
    2886                 : /* -------------------------------------------------------------------- */
    2887              20 :         for( int iSampleBlock = 0; 
    2888                 :              iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
    2889                 :              iSampleBlock += nSampleRate )
    2890                 :         {
    2891                 :             int  iXBlock, iYBlock, nXCheck, nYCheck;
    2892                 :             GDALRasterBlock *poBlock;
    2893                 :             void* pData;
    2894                 : 
    2895              16 :             if( !pfnProgress( iSampleBlock
    2896                 :                               / ((double)nBlocksPerRow * nBlocksPerColumn),
    2897                 :                               "Compute Histogram", pProgressData ) )
    2898               0 :                 return CE_Failure;
    2899                 : 
    2900              16 :             iYBlock = iSampleBlock / nBlocksPerRow;
    2901              16 :             iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
    2902                 :             
    2903              16 :             poBlock = GetLockedBlockRef( iXBlock, iYBlock );
    2904              16 :             if( poBlock == NULL )
    2905               0 :                 return CE_Failure;
    2906              16 :             if( poBlock->GetDataRef() == NULL )
    2907                 :             {
    2908               0 :                 poBlock->DropLock();
    2909               0 :                 return CE_Failure;
    2910                 :             }
    2911                 :             
    2912              16 :             pData = poBlock->GetDataRef();
    2913                 :             
    2914              16 :             if( (iXBlock+1) * nBlockXSize > GetXSize() )
    2915               0 :                 nXCheck = GetXSize() - iXBlock * nBlockXSize;
    2916                 :             else
    2917              16 :                 nXCheck = nBlockXSize;
    2918                 : 
    2919              16 :             if( (iYBlock+1) * nBlockYSize > GetYSize() )
    2920               2 :                 nYCheck = GetYSize() - iYBlock * nBlockYSize;
    2921                 :             else
    2922              14 :                 nYCheck = nBlockYSize;
    2923                 : 
    2924                 :             /* this is a special case for a common situation */
    2925              16 :             if( eDataType == GDT_Byte && !bSignedByte
    2926                 :                 && dfScale == 1.0 && (dfMin >= -0.5 && dfMin <= 0.5)
    2927                 :                 && nYCheck == nBlockYSize && nXCheck == nBlockXSize
    2928                 :                 && nBuckets == 256 )
    2929                 :             {
    2930               1 :                 int    nPixels = nXCheck * nYCheck;
    2931               1 :                 GByte  *pabyData = (GByte *) pData;
    2932                 :                 
    2933            8101 :                 for( int i = 0; i < nPixels; i++ )
    2934            8100 :                     panHistogram[pabyData[i]]++;
    2935                 : 
    2936               1 :                 poBlock->DropLock();
    2937               1 :                 continue; /* to next sample block */
    2938                 :             }
    2939                 : 
    2940                 :             /* this isn't the fastest way to do this, but is easier for now */
    2941             146 :             for( int iY = 0; iY < nYCheck; iY++ )
    2942                 :             {
    2943           12091 :                 for( int iX = 0; iX < nXCheck; iX++ )
    2944                 :                 {
    2945           11960 :                     int    iOffset = iX + iY * nBlockXSize;
    2946                 :                     int    nIndex;
    2947           11960 :                     double dfValue = 0.0;
    2948                 : 
    2949           11960 :                     switch( eDataType )
    2950                 :                     {
    2951                 :                       case GDT_Byte:
    2952                 :                       {
    2953           11900 :                         if (bSignedByte)
    2954               0 :                             dfValue = ((signed char *) pData)[iOffset];
    2955                 :                         else
    2956           11900 :                             dfValue = ((GByte *) pData)[iOffset];
    2957           11900 :                         break;
    2958                 :                       }
    2959                 :                       case GDT_UInt16:
    2960               0 :                         dfValue = ((GUInt16 *) pData)[iOffset];
    2961               0 :                         break;
    2962                 :                       case GDT_Int16:
    2963               0 :                         dfValue = ((GInt16 *) pData)[iOffset];
    2964               0 :                         break;
    2965                 :                       case GDT_UInt32:
    2966               0 :                         dfValue = ((GUInt32 *) pData)[iOffset];
    2967               0 :                         break;
    2968                 :                       case GDT_Int32:
    2969              60 :                         dfValue = ((GInt32 *) pData)[iOffset];
    2970              60 :                         break;
    2971                 :                       case GDT_Float32:
    2972               0 :                         dfValue = ((float *) pData)[iOffset];
    2973               0 :                         break;
    2974                 :                       case GDT_Float64:
    2975               0 :                         dfValue = ((double *) pData)[iOffset];
    2976               0 :                         break;
    2977                 :                       case GDT_CInt16:
    2978                 :                         {
    2979                 :                             double  dfReal =
    2980               0 :                                 ((GInt16 *) pData)[iOffset*2];
    2981                 :                             double  dfImag =
    2982               0 :                                 ((GInt16 *) pData)[iOffset*2+1];
    2983               0 :                             if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
    2984               0 :                                 continue;
    2985               0 :                             dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    2986                 :                         }
    2987               0 :                         break;
    2988                 :                       case GDT_CInt32:
    2989                 :                         {
    2990                 :                             double  dfReal =
    2991               0 :                                 ((GInt32 *) pData)[iOffset*2];
    2992                 :                             double  dfImag =
    2993               0 :                                 ((GInt32 *) pData)[iOffset*2+1];
    2994               0 :                             if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
    2995               0 :                                 continue;
    2996               0 :                             dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    2997                 :                         }
    2998               0 :                         break;
    2999                 :                       case GDT_CFloat32:
    3000                 :                         {
    3001                 :                             double  dfReal =
    3002               0 :                                 ((float *) pData)[iOffset*2];
    3003                 :                             double  dfImag =
    3004               0 :                                 ((float *) pData)[iOffset*2+1];
    3005               0 :                             if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
    3006               0 :                                 continue;
    3007               0 :                             dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    3008                 :                         }
    3009               0 :                         break;
    3010                 :                       case GDT_CFloat64:
    3011                 :                         {
    3012                 :                             double  dfReal =
    3013               0 :                                 ((double *) pData)[iOffset*2];
    3014                 :                             double  dfImag =
    3015               0 :                                 ((double *) pData)[iOffset*2+1];
    3016               0 :                             if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
    3017               0 :                                 continue;
    3018               0 :                             dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
    3019                 :                         }
    3020               0 :                         break;
    3021                 :                       default:
    3022                 :                         CPLAssert( FALSE );
    3023               0 :                         return CE_Failure;
    3024                 :                     }
    3025                 :                     
    3026           11960 :                     nIndex = (int) floor((dfValue - dfMin) * dfScale);
    3027                 : 
    3028           11960 :                     if( nIndex < 0 )
    3029                 :                     {
    3030               0 :                         if( bIncludeOutOfRange )
    3031               0 :                             panHistogram[0]++;
    3032                 :                     }
    3033           11960 :                     else if( nIndex >= nBuckets )
    3034                 :                     {
    3035               6 :                         if( bIncludeOutOfRange )
    3036               3 :                             panHistogram[nBuckets-1]++;
    3037                 :                     }
    3038                 :                     else
    3039                 :                     {
    3040           11954 :                         panHistogram[nIndex]++;
    3041                 :                     }
    3042                 :                 }
    3043                 :             }
    3044                 : 
    3045              15 :             poBlock->DropLock();
    3046                 :         }
    3047                 :     }
    3048                 : 
    3049               4 :     pfnProgress( 1.0, "Compute Histogram", pProgressData );
    3050                 : 
    3051               4 :     return CE_None;
    3052                 : }
    3053                 : 
    3054                 : /************************************************************************/
    3055                 : /*                       GDALGetRasterHistogram()                       */
    3056                 : /************************************************************************/
    3057                 : 
    3058                 : /**
    3059                 :  * \brief Compute raster histogram. 
    3060                 :  *
    3061                 :  * @see GDALRasterBand::GetHistogram()
    3062                 :  */
    3063                 : 
    3064                 : CPLErr CPL_STDCALL 
    3065               4 : GDALGetRasterHistogram( GDALRasterBandH hBand, 
    3066                 :                         double dfMin, double dfMax, 
    3067                 :                         int nBuckets, int *panHistogram, 
    3068                 :                         int bIncludeOutOfRange, int bApproxOK,
    3069                 :                         GDALProgressFunc pfnProgress, 
    3070                 :                         void *pProgressData )
    3071                 :     
    3072                 : {
    3073               4 :     VALIDATE_POINTER1( hBand, "GDALGetRasterHistogram", CE_Failure );
    3074               4 :     VALIDATE_POINTER1( panHistogram, "GDALGetRasterHistogram", CE_Failure );
    3075                 : 
    3076               4 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    3077                 : 
    3078                 :     return poBand->GetHistogram( dfMin, dfMax, nBuckets, panHistogram, 
    3079                 :                       bIncludeOutOfRange, bApproxOK,
    3080               4 :                       pfnProgress, pProgressData );
    3081                 : }
    3082                 : 
    3083                 : /************************************************************************/
    3084                 : /*                        GetDefaultHistogram()                         */
    3085                 : /************************************************************************/
    3086                 : 
    3087                 : /**
    3088                 :  * \brief Fetch default raster histogram. 
    3089                 :  *
    3090                 :  * The default method in GDALRasterBand will compute a default histogram. This
    3091                 :  * method is overriden by derived classes (such as GDALPamRasterBand, VRTDataset, HFADataset...)
    3092                 :  * that may be able to fetch efficiently an already stored histogram.
    3093                 :  *
    3094                 :  * @param pdfMin pointer to double value that will contain the lower bound of the histogram.
    3095                 :  * @param pdfMax pointer to double value that will contain the upper bound of the histogram.
    3096                 :  * @param pnBuckets pointer to int value that will contain the number of buckets in *ppanHistogram.
    3097                 :  * @param ppanHistogram pointer to array into which the histogram totals are placed. To be freed with VSIFree
    3098                 :  * @param bForce TRUE to force the computation. If FALSE and no default histogram is available, the method will return CE_Warning
    3099                 :  * @param pfnProgress function to report progress to completion. 
    3100                 :  * @param pProgressData application data to pass to pfnProgress. 
    3101                 :  *
    3102                 :  * @return CE_None on success, CE_Failure if something goes wrong, or 
    3103                 :  * CE_Warning if no default histogram is available.
    3104                 :  */
    3105                 : 
    3106                 : CPLErr 
    3107               3 :     GDALRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax, 
    3108                 :                                          int *pnBuckets, int **ppanHistogram, 
    3109                 :                                          int bForce,
    3110                 :                                          GDALProgressFunc pfnProgress, 
    3111                 :                                          void *pProgressData )
    3112                 : 
    3113                 : {
    3114                 :     CPLAssert( NULL != pnBuckets );
    3115                 :     CPLAssert( NULL != ppanHistogram );
    3116                 :     CPLAssert( NULL != pdfMin );
    3117                 :     CPLAssert( NULL != pdfMax );
    3118                 : 
    3119               3 :     *pnBuckets = 0;
    3120               3 :     *ppanHistogram = NULL;
    3121                 : 
    3122               3 :     if( !bForce )
    3123               3 :         return CE_Warning;
    3124                 : 
    3125               0 :     int nBuckets = 256;
    3126                 :     
    3127               0 :     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
    3128               0 :     int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
    3129                 : 
    3130               0 :     if( GetRasterDataType() == GDT_Byte && !bSignedByte)
    3131                 :     {
    3132               0 :         *pdfMin = -0.5;
    3133               0 :         *pdfMax = 255.5;
    3134                 :     }
    3135                 :     else
    3136                 :     {
    3137               0 :         CPLErr eErr = CE_Failure;
    3138               0 :         double dfHalfBucket = 0;
    3139                 : 
    3140               0 :         eErr = GetStatistics( TRUE, TRUE, pdfMin, pdfMax, NULL, NULL );
    3141               0 :         dfHalfBucket = (*pdfMax - *pdfMin) / (2 * nBuckets);
    3142               0 :         *pdfMin -= dfHalfBucket;
    3143               0 :         *pdfMax += dfHalfBucket;
    3144                 : 
    3145               0 :         if( eErr != CE_None )
    3146               0 :             return eErr;
    3147                 :     }
    3148                 : 
    3149               0 :     *ppanHistogram = (int *) VSICalloc(sizeof(int), nBuckets);
    3150               0 :     if( *ppanHistogram == NULL )
    3151                 :     {
    3152                 :         CPLError( CE_Failure, CPLE_OutOfMemory,
    3153               0 :                   "Out of memory in InitBlockInfo()." );
    3154               0 :         return CE_Failure;
    3155                 :     }
    3156                 : 
    3157               0 :     *pnBuckets = nBuckets;
    3158                 :     return GetHistogram( *pdfMin, *pdfMax, *pnBuckets, *ppanHistogram, 
    3159               0 :                          TRUE, FALSE, pfnProgress, pProgressData );
    3160                 : }
    3161                 : 
    3162                 : /************************************************************************/
    3163                 : /*                      GDALGetDefaultHistogram()                       */
    3164                 : /************************************************************************/
    3165                 : 
    3166                 : /**
    3167                 :   * \brief Fetch default raster histogram. 
    3168                 :   *
    3169                 :   * @see GDALRasterBand::GetDefaultHistogram()
    3170                 :   */
    3171                 : 
    3172               2 : CPLErr CPL_STDCALL GDALGetDefaultHistogram( GDALRasterBandH hBand, 
    3173                 :                                 double *pdfMin, double *pdfMax, 
    3174                 :                                 int *pnBuckets, int **ppanHistogram, 
    3175                 :                                 int bForce,
    3176                 :                                 GDALProgressFunc pfnProgress, 
    3177                 :                                 void *pProgressData )
    3178                 : 
    3179                 : {
    3180               2 :     VALIDATE_POINTER1( hBand, "GDALGetDefaultHistogram", CE_Failure );
    3181               2 :     VALIDATE_POINTER1( pdfMin, "GDALGetDefaultHistogram", CE_Failure );
    3182               2 :     VALIDATE_POINTER1( pdfMax, "GDALGetDefaultHistogram", CE_Failure );
    3183               2 :     VALIDATE_POINTER1( pnBuckets, "GDALGetDefaultHistogram", CE_Failure );
    3184               2 :     VALIDATE_POINTER1( ppanHistogram, "GDALGetDefaultHistogram", CE_Failure );
    3185                 : 
    3186               2 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    3187                 :     return poBand->GetDefaultHistogram( pdfMin, pdfMax,
    3188               2 :         pnBuckets, ppanHistogram, bForce, pfnProgress, pProgressData );
    3189                 : }
    3190                 : 
    3191                 : /************************************************************************/
    3192                 : /*                             AdviseRead()                             */
    3193                 : /************************************************************************/
    3194                 : 
    3195                 : /**
    3196                 :  * \brief Advise driver of upcoming read requests.
    3197                 :  *
    3198                 :  * Some GDAL drivers operate more efficiently if they know in advance what 
    3199                 :  * set of upcoming read requests will be made.  The AdviseRead() method allows
    3200                 :  * an application to notify the driver of the region of interest, 
    3201                 :  * and at what resolution the region will be read.  
    3202                 :  *
    3203                 :  * Many drivers just ignore the AdviseRead() call, but it can dramatically
    3204                 :  * accelerate access via some drivers.  
    3205                 :  *
    3206                 :  * @param nXOff The pixel offset to the top left corner of the region
    3207                 :  * of the band to be accessed.  This would be zero to start from the left side.
    3208                 :  *
    3209                 :  * @param nYOff The line offset to the top left corner of the region
    3210                 :  * of the band to be accessed.  This would be zero to start from the top.
    3211                 :  *
    3212                 :  * @param nXSize The width of the region of the band to be accessed in pixels.
    3213                 :  *
    3214                 :  * @param nYSize The height of the region of the band to be accessed in lines.
    3215                 :  *
    3216                 :  * @param nBufXSize the width of the buffer image into which the desired region
    3217                 :  * is to be read, or from which it is to be written.
    3218                 :  *
    3219                 :  * @param nBufYSize the height of the buffer image into which the desired
    3220                 :  * region is to be read, or from which it is to be written.
    3221                 :  *
    3222                 :  * @param eBufType the type of the pixel values in the pData data buffer.  The
    3223                 :  * pixel values will automatically be translated to/from the GDALRasterBand
    3224                 :  * data type as needed.
    3225                 :  *
    3226                 :  * @param papszOptions a list of name=value strings with special control 
    3227                 :  * options.  Normally this is NULL.
    3228                 :  *
    3229                 :  * @return CE_Failure if the request is invalid and CE_None if it works or
    3230                 :  * is ignored. 
    3231                 :  */
    3232                 : 
    3233               0 : CPLErr GDALRasterBand::AdviseRead( 
    3234                 :     int nXOff, int nYOff, int nXSize, int nYSize,
    3235                 :     int nBufXSize, int nBufYSize, GDALDataType eDT, char **papszOptions )
    3236                 : 
    3237                 : {
    3238               0 :     return CE_None;
    3239                 : }
    3240                 : 
    3241                 : /************************************************************************/
    3242                 : /*                        GDALRasterAdviseRead()                        */
    3243                 : /************************************************************************/
    3244                 : 
    3245                 : 
    3246                 : /**
    3247                 :  * \brief Advise driver of upcoming read requests.
    3248                 :  *
    3249                 :  * @see GDALRasterBand::AdviseRead()
    3250                 :  */
    3251                 : 
    3252                 : CPLErr CPL_STDCALL 
    3253               0 : GDALRasterAdviseRead( GDALRasterBandH hBand, 
    3254                 :                       int nXOff, int nYOff, int nXSize, int nYSize,
    3255                 :                       int nBufXSize, int nBufYSize, 
    3256                 :                       GDALDataType eDT, char **papszOptions )
    3257                 :     
    3258                 : {
    3259               0 :     VALIDATE_POINTER1( hBand, "GDALRasterAdviseRead", CE_Failure );
    3260                 : 
    3261               0 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    3262                 :     return poBand->AdviseRead( nXOff, nYOff, nXSize, nYSize, 
    3263               0 :         nBufXSize, nBufYSize, eDT, papszOptions );
    3264                 : }
    3265                 : 
    3266                 : /************************************************************************/
    3267                 : /*                           GetStatistics()                            */
    3268                 : /************************************************************************/
    3269                 : 
    3270                 : /**
    3271                 :  * \brief Fetch image statistics. 
    3272                 :  *
    3273                 :  * Returns the minimum, maximum, mean and standard deviation of all
    3274                 :  * pixel values in this band.  If approximate statistics are sufficient,
    3275                 :  * the bApproxOK flag can be set to true in which case overviews, or a
    3276                 :  * subset of image tiles may be used in computing the statistics.  
    3277                 :  *
    3278                 :  * If bForce is FALSE results will only be returned if it can be done 
    3279                 :  * quickly (ie. without scanning the data).  If bForce is FALSE and 
    3280                 :  * results cannot be returned efficiently, the method will return CE_Warning
    3281                 :  * but no warning will have been issued.   This is a non-standard use of
    3282                 :  * the CE_Warning return value to indicate "nothing done". 
    3283                 :  *
    3284                 :  * Note that file formats using PAM (Persistent Auxilary Metadata) services
    3285                 :  * will generally cache statistics in the .pam file allowing fast fetch
    3286                 :  * after the first request. 
    3287                 :  *
    3288                 :  * This method is the same as the C function GDALGetRasterStatistics().
    3289                 :  *
    3290                 :  * @param bApproxOK If TRUE statistics may be computed based on overviews
    3291                 :  * or a subset of all tiles. 
    3292                 :  * 
    3293                 :  * @param bForce If FALSE statistics will only be returned if it can
    3294                 :  * be done without rescanning the image. 
    3295                 :  *
    3296                 :  * @param pdfMin Location into which to load image minimum (may be NULL).
    3297                 :  *
    3298                 :  * @param pdfMax Location into which to load image maximum (may be NULL).-
    3299                 :  *
    3300                 :  * @param pdfMean Location into which to load image mean (may be NULL).
    3301                 :  *
    3302                 :  * @param pdfStdDev Location into which to load image standard deviation 
    3303                 :  * (may be NULL).
    3304                 :  *
    3305                 :  * @return CE_None on success, CE_Warning if no values returned, 
    3306                 :  * CE_Failure if an error occurs.
    3307                 :  */
    3308                 : 
    3309              62 : CPLErr GDALRasterBand::GetStatistics( int bApproxOK, int bForce,
    3310                 :                                       double *pdfMin, double *pdfMax, 
    3311                 :                                       double *pdfMean, double *pdfStdDev )
    3312                 : 
    3313                 : {
    3314              62 :     double       dfMin=0.0, dfMax=0.0;
    3315                 : 
    3316                 : /* -------------------------------------------------------------------- */
    3317                 : /*      Do we already have metadata items for the requested values?     */
    3318                 : /* -------------------------------------------------------------------- */
    3319             104 :     if( (pdfMin == NULL || GetMetadataItem("STATISTICS_MINIMUM") != NULL)
    3320              14 :      && (pdfMax == NULL || GetMetadataItem("STATISTICS_MAXIMUM") != NULL)
    3321              14 :      && (pdfMean == NULL || GetMetadataItem("STATISTICS_MEAN") != NULL)
    3322              14 :      && (pdfStdDev == NULL || GetMetadataItem("STATISTICS_STDDEV") != NULL) )
    3323                 :     {
    3324              14 :         if( pdfMin != NULL )
    3325              14 :             *pdfMin = atof(GetMetadataItem("STATISTICS_MINIMUM"));
    3326              14 :         if( pdfMax != NULL )
    3327              14 :             *pdfMax = atof(GetMetadataItem("STATISTICS_MAXIMUM"));
    3328              14 :         if( pdfMean != NULL )
    3329              14 :             *pdfMean = atof(GetMetadataItem("STATISTICS_MEAN"));
    3330              14 :         if( pdfStdDev != NULL )
    3331              14 :             *pdfStdDev = atof(GetMetadataItem("STATISTICS_STDDEV"));
    3332                 : 
    3333              14 :         return CE_None;
    3334                 :     }
    3335                 : 
    3336                 : /* -------------------------------------------------------------------- */
    3337                 : /*      Does the driver already know the min/max?                       */
    3338                 : /* -------------------------------------------------------------------- */
    3339              48 :     if( bApproxOK && pdfMean == NULL && pdfStdDev == NULL )
    3340                 :     {
    3341                 :         int          bSuccessMin, bSuccessMax;
    3342                 : 
    3343               0 :         dfMin = GetMinimum( &bSuccessMin );
    3344               0 :         dfMax = GetMaximum( &bSuccessMax );
    3345                 : 
    3346               0 :         if( bSuccessMin && bSuccessMax )
    3347                 :         {
    3348               0 :             if( pdfMin != NULL )
    3349               0 :                 *pdfMin = dfMin;
    3350               0 :             if( pdfMax != NULL )
    3351               0 :                 *pdfMax = dfMax;
    3352               0 :             return CE_None;
    3353                 :         }
    3354                 :     }
    3355                 :     
    3356                 : /* -------------------------------------------------------------------- */
    3357                 : /*      Either return without results, or force computation.            */
    3358                 : /* -------------------------------------------------------------------- */
    3359              48 :     if( !bForce )
    3360              12 :         return CE_Warning;
    3361                 :     else
    3362                 :         return ComputeStatistics( bApproxOK, 
    3363                 :                                   pdfMin, pdfMax, pdfMean, pdfStdDev,
    3364              36 :                                   GDALDummyProgress, NULL );
    3365                 : }
    3366                 : 
    3367                 : /************************************************************************/
    3368                 : /*                      GDALGetRasterStatistics()                       */
    3369                 : /************************************************************************/
    3370                 : 
    3371                 : /**
    3372                 :  * \brief Fetch image statistics. 
    3373                 :  *
    3374                 :  * @see GDALRasterBand::GetStatistics()
    3375                 :  */
    3376                 : 
    3377              38 : CPLErr CPL_STDCALL GDALGetRasterStatistics( 
    3378                 :         GDALRasterBandH hBand, int bApproxOK, int bForce, 
    3379                 :         double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev )
    3380                 : 
    3381                 : {
    3382              38 :     VALIDATE_POINTER1( hBand, "GDALGetRasterStatistics", CE_Failure );
    3383                 : 
    3384              38 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    3385                 :     return poBand->GetStatistics( 
    3386              38 :         bApproxOK, bForce, pdfMin, pdfMax, pdfMean, pdfStdDev );
    3387                 : }
    3388                 : 
    3389                 : /************************************************************************/
    3390                 : /*                         ComputeStatistics()                          */
    3391                 : /************************************************************************/
    3392                 : 
    3393                 : /**
    3394                 :  * \brief Compute image statistics. 
    3395                 :  *
    3396                 :  * Returns the minimum, maximum, mean and standard deviation of all
    3397                 :  * pixel values in this band.  If approximate statistics are sufficient,
    3398                 :  * the bApproxOK flag can be set to true in which case overviews, or a
    3399                 :  * subset of image tiles may be used in computing the statistics.  
    3400                 :  *
    3401                 :  * Once computed, the statistics will generally be "set" back on the 
    3402                 :  * raster band using SetStatistics(). 
    3403                 :  *
    3404                 :  * This method is the same as the C function GDALComputeRasterStatistics().
    3405                 :  *
    3406                 :  * @param bApproxOK If TRUE statistics may be computed based on overviews
    3407                 :  * or a subset of all tiles. 
    3408                 :  * 
    3409                 :  * @param pdfMin Location into which to load image minimum (may be NULL).
    3410                 :  *
    3411                 :  * @param pdfMax Location into which to load image maximum (may be NULL).-
    3412                 :  *
    3413                 :  * @param pdfMean Location into which to load image mean (may be NULL).
    3414                 :  *
    3415                 :  * @param pdfStdDev Location into which to load image standard deviation 
    3416                 :  * (may be NULL).
    3417                 :  *
    3418                 :  * @param pfnProgress a function to call to report progress, or NULL.
    3419                 :  *
    3420                 :  * @param pProgressData application data to pass to the progress function.
    3421                 :  *
    3422                 :  * @return CE_None on success, or CE_Failure if an error occurs or processing
    3423                 :  * is terminated by the user.
    3424                 :  */
    3425                 : 
    3426                 : CPLErr 
    3427              40 : GDALRasterBand::ComputeStatistics( int bApproxOK,
    3428                 :                                    double *pdfMin, double *pdfMax, 
    3429                 :                                    double *pdfMean, double *pdfStdDev,
    3430                 :                                    GDALProgressFunc pfnProgress, 
    3431                 :                                    void *pProgressData )
    3432                 : 
    3433                 : {
    3434              40 :     if( pfnProgress == NULL )
    3435               0 :         pfnProgress = GDALDummyProgress;
    3436                 : 
    3437                 : /* -------------------------------------------------------------------- */
    3438                 : /*      If we have overview bands, use them for statistics.             */
    3439                 : /* -------------------------------------------------------------------- */
    3440              40 :     if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
    3441                 :     {
    3442                 :         GDALRasterBand *poBand;
    3443                 : 
    3444               4 :         poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
    3445                 : 
    3446               4 :         if( poBand != this )
    3447                 :             return poBand->ComputeStatistics( FALSE,  
    3448                 :                                               pdfMin, pdfMax, 
    3449                 :                                               pdfMean, pdfStdDev,
    3450               4 :                                               pfnProgress, pProgressData );
    3451                 :     }
    3452                 : 
    3453                 : /* -------------------------------------------------------------------- */
    3454                 : /*      Read actual data and compute statistics.                        */
    3455                 : /* -------------------------------------------------------------------- */
    3456              36 :     double      dfMin = 0.0, dfMax = 0.0;
    3457              36 :     int         bGotNoDataValue, bFirstValue = TRUE;
    3458              36 :     double      dfNoDataValue, dfSum = 0.0, dfSum2 = 0.0;
    3459              36 :     GIntBig     nSampleCount = 0;
    3460                 : 
    3461              36 :     if( !pfnProgress( 0.0, "Compute Statistics", pProgressData ) )
    3462                 :     {
    3463               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3464               0 :         return CE_Failure;
    3465                 :     }
    3466                 : 
    3467              36 :     dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
    3468                 : 
    3469              36 :     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
    3470              36 :     int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
    3471                 :     
    3472              36 :     if ( bApproxOK && HasArbitraryOverviews() )
    3473                 :     {
    3474                 : /* -------------------------------------------------------------------- */
    3475                 : /*      Figure out how much the image should be reduced to get an       */
    3476                 : /*      approximate value.                                              */
    3477                 : /* -------------------------------------------------------------------- */
    3478                 :         void    *pData;
    3479                 :         int     nXReduced, nYReduced;
    3480                 :         double  dfReduction = sqrt(
    3481               0 :             (double)nRasterXSize * nRasterYSize / GDALSTAT_APPROX_NUMSAMPLES );
    3482                 : 
    3483               0 :         if ( dfReduction > 1.0 )
    3484                 :         {
    3485               0 :             nXReduced = (int)( nRasterXSize / dfReduction );
    3486               0 :             nYReduced = (int)( nRasterYSize / dfReduction );
    3487                 : 
    3488                 :             // Catch the case of huge resizing ratios here
    3489               0 :             if ( nXReduced == 0 )
    3490               0 :                 nXReduced = 1;
    3491               0 :             if ( nYReduced == 0 )
    3492               0 :                 nYReduced = 1;
    3493                 :         }
    3494                 :         else
    3495                 :         {
    3496               0 :             nXReduced = nRasterXSize;
    3497               0 :             nYReduced = nRasterYSize;
    3498                 :         }
    3499                 : 
    3500                 :         pData =
    3501               0 :             CPLMalloc(GDALGetDataTypeSize(eDataType)/8 * nXReduced * nYReduced);
    3502                 : 
    3503                 :         CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
    3504               0 :                    nXReduced, nYReduced, eDataType, 0, 0 );
    3505               0 :         if ( eErr != CE_None )
    3506                 :         {
    3507               0 :             CPLFree(pData);
    3508               0 :             return eErr;
    3509                 :         }
    3510                 : 
    3511                 :         /* this isn't the fastest way to do this, but is easier for now */
    3512               0 :         for( int iY = 0; iY < nYReduced; iY++ )
    3513                 :         {
    3514               0 :             for( int iX = 0; iX < nXReduced; iX++ )
    3515                 :             {
    3516               0 :                 int    iOffset = iX + iY * nXReduced;
    3517               0 :                 double dfValue = 0.0;
    3518                 : 
    3519               0 :                 switch( eDataType )
    3520                 :                 {
    3521                 :                   case GDT_Byte:
    3522                 :                   {
    3523               0 :                     if (bSignedByte)
    3524               0 :                         dfValue = ((signed char *)pData)[iOffset];
    3525                 :                     else
    3526               0 :                         dfValue = ((GByte *)pData)[iOffset];
    3527               0 :                     break;
    3528                 :                   }
    3529                 :                   case GDT_UInt16:
    3530               0 :                     dfValue = ((GUInt16 *)pData)[iOffset];
    3531               0 :                     break;
    3532                 :                   case GDT_Int16:
    3533               0 :                     dfValue = ((GInt16 *)pData)[iOffset];
    3534               0 :                     break;
    3535                 :                   case GDT_UInt32:
    3536               0 :                     dfValue = ((GUInt32 *)pData)[iOffset];
    3537               0 :                     break;
    3538                 :                   case GDT_Int32:
    3539               0 :                     dfValue = ((GInt32 *)pData)[iOffset];
    3540               0 :                     break;
    3541                 :                   case GDT_Float32:
    3542               0 :                     dfValue = ((float *)pData)[iOffset];
    3543               0 :                     if (CPLIsNan(dfValue))
    3544               0 :                         continue;
    3545               0 :                     break;
    3546                 :                   case GDT_Float64:
    3547               0 :                     dfValue = ((double *)pData)[iOffset];
    3548               0 :                     if (CPLIsNan(dfValue))
    3549               0 :                         continue;
    3550               0 :                     break;
    3551                 :                   case GDT_CInt16:
    3552               0 :                     dfValue = ((GInt16 *)pData)[iOffset*2];
    3553               0 :                     break;
    3554                 :                   case GDT_CInt32:
    3555               0 :                     dfValue = ((GInt32 *)pData)[iOffset*2];
    3556               0 :                     break;
    3557                 :                   case GDT_CFloat32:
    3558               0 :                     dfValue = ((float *)pData)[iOffset*2];
    3559               0 :                     if( CPLIsNan(dfValue) )
    3560               0 :                         continue;
    3561               0 :                     break;
    3562                 :                   case GDT_CFloat64:
    3563               0 :                     dfValue = ((double *)pData)[iOffset*2];
    3564               0 :                     if( CPLIsNan(dfValue) )
    3565               0 :                         continue;
    3566                 :                     break;
    3567                 :                   default:
    3568                 :                     CPLAssert( FALSE );
    3569                 :                 }
    3570                 :                 
    3571               0 :                 if( bGotNoDataValue && dfValue == dfNoDataValue )
    3572               0 :                     continue;
    3573                 : 
    3574               0 :                 if( bFirstValue )
    3575                 :                 {
    3576               0 :                     dfMin = dfMax = dfValue;
    3577               0 :                     bFirstValue = FALSE;
    3578                 :                 }
    3579                 :                 else
    3580                 :                 {
    3581               0 :                     dfMin = MIN(dfMin,dfValue);
    3582               0 :                     dfMax = MAX(dfMax,dfValue);
    3583                 :                 }
    3584                 : 
    3585               0 :                 dfSum += dfValue;
    3586               0 :                 dfSum2 += dfValue * dfValue;
    3587                 : 
    3588               0 :                 nSampleCount++;
    3589                 :             }
    3590                 :         }
    3591                 : 
    3592               0 :         CPLFree( pData );
    3593                 :     }
    3594                 : 
    3595                 :     else    // No arbitrary overviews
    3596                 :     {
    3597                 :         int     nSampleRate;
    3598                 :         
    3599              36 :         if( !InitBlockInfo() )
    3600               0 :             return CE_Failure;
    3601                 : 
    3602                 : /* -------------------------------------------------------------------- */
    3603                 : /*      Figure out the ratio of blocks we will read to get an           */
    3604                 : /*      approximate value.                                              */
    3605                 : /* -------------------------------------------------------------------- */
    3606              36 :         if ( bApproxOK )
    3607                 :         {
    3608                 :             nSampleRate = 
    3609               1 :                 (int)MAX( 1, sqrt((double)nBlocksPerRow * nBlocksPerColumn) );
    3610                 :         }
    3611                 :         else
    3612              35 :             nSampleRate = 1;
    3613                 : 
    3614             362 :         for( int iSampleBlock = 0; 
    3615                 :              iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
    3616                 :              iSampleBlock += nSampleRate )
    3617                 :         {
    3618                 :             int  iXBlock, iYBlock, nXCheck, nYCheck;
    3619                 :             GDALRasterBlock *poBlock;
    3620                 :             void* pData;
    3621                 : 
    3622             326 :             iYBlock = iSampleBlock / nBlocksPerRow;
    3623             326 :             iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
    3624                 :             
    3625             326 :             poBlock = GetLockedBlockRef( iXBlock, iYBlock );
    3626             326 :             if( poBlock == NULL )
    3627               0 :                 continue;
    3628             326 :             if( poBlock->GetDataRef() == NULL )
    3629                 :             {
    3630               0 :                 poBlock->DropLock();
    3631               0 :                 continue;
    3632                 :             }
    3633                 :             
    3634             326 :             pData = poBlock->GetDataRef();
    3635                 :             
    3636             326 :             if( (iXBlock+1) * nBlockXSize > GetXSize() )
    3637               2 :                 nXCheck = GetXSize() - iXBlock * nBlockXSize;
    3638                 :             else
    3639             324 :                 nXCheck = nBlockXSize;
    3640                 : 
    3641             326 :             if( (iYBlock+1) * nBlockYSize > GetYSize() )
    3642               4 :                 nYCheck = GetYSize() - iYBlock * nBlockYSize;
    3643                 :             else
    3644             322 :                 nYCheck = nBlockYSize;
    3645                 : 
    3646                 :             /* this isn't the fastest way to do this, but is easier for now */
    3647            8430 :             for( int iY = 0; iY < nYCheck; iY++ )
    3648                 :             {
    3649         6897046 :                 for( int iX = 0; iX < nXCheck; iX++ )
    3650                 :                 {
    3651         6888942 :                     int    iOffset = iX + iY * nBlockXSize;
    3652         6888942 :                     double dfValue = 0.0;
    3653                 : 
    3654         6888942 :                     switch( eDataType )
    3655                 :                     {
    3656                 :                       case GDT_Byte:
    3657                 :                       {
    3658          580493 :                         if (bSignedByte)
    3659               5 :                             dfValue = ((signed char *)pData)[iOffset];
    3660                 :                         else
    3661          580488 :                             dfValue = ((GByte *)pData)[iOffset];
    3662          580493 :                         break;
    3663                 :                       }
    3664                 :                       case GDT_UInt16:
    3665         6307940 :                         dfValue = ((GUInt16 *)pData)[iOffset];
    3666         6307940 :                         break;
    3667                 :                       case GDT_Int16:
    3668             100 :                         dfValue = ((GInt16 *)pData)[iOffset];
    3669             100 :                         break;
    3670                 :                       case GDT_UInt32:
    3671             100 :                         dfValue = ((GUInt32 *)pData)[iOffset];
    3672             100 :                         break;
    3673                 :                       case GDT_Int32:
    3674             100 :                         dfValue = ((GInt32 *)pData)[iOffset];
    3675             100 :                         break;
    3676                 :                       case GDT_Float32:
    3677             109 :                         dfValue = ((float *)pData)[iOffset];
    3678             109 :                         if (CPLIsNan(dfValue))
    3679               0 :                             continue;
    3680             109 :                         break;
    3681                 :                       case GDT_Float64:
    3682             100 :                         dfValue = ((double *)pData)[iOffset];
    3683             100 :                         if (CPLIsNan(dfValue))
    3684               0 :                             continue;
    3685             100 :                         break;
    3686                 :                       case GDT_CInt16:
    3687               0 :                         dfValue = ((GInt16 *)pData)[iOffset*2];
    3688               0 :                         break;
    3689                 :                       case GDT_CInt32:
    3690               0 :                         dfValue = ((GInt32 *)pData)[iOffset*2];
    3691               0 :                         break;
    3692                 :                       case GDT_CFloat32:
    3693               0 :                         dfValue = ((float *)pData)[iOffset*2];
    3694               0 :                         if( CPLIsNan(dfValue) )
    3695               0 :                             continue;
    3696               0 :                         break;
    3697                 :                       case GDT_CFloat64:
    3698               0 :                         dfValue = ((double *)pData)[iOffset*2];
    3699               0 :                         if( CPLIsNan(dfValue) )
    3700               0 :                             continue;
    3701                 :                         break;
    3702                 :                       default:
    3703                 :                         CPLAssert( FALSE );
    3704                 :                     }
    3705                 :                     
    3706         6888942 :                     if( bGotNoDataValue && dfValue == dfNoDataValue )
    3707              30 :                         continue;
    3708                 : 
    3709         6888912 :                     if( bFirstValue )
    3710                 :                     {
    3711              36 :                         dfMin = dfMax = dfValue;
    3712              36 :                         bFirstValue = FALSE;
    3713                 :                     }
    3714                 :                     else
    3715                 :                     {
    3716         6888876 :                         dfMin = MIN(dfMin,dfValue);
    3717         6888876 :                         dfMax = MAX(dfMax,dfValue);
    3718                 :                     }
    3719                 : 
    3720         6888912 :                     dfSum += dfValue;
    3721         6888912 :                     dfSum2 += dfValue * dfValue;
    3722                 : 
    3723         6888912 :                     nSampleCount++;
    3724                 :                 }
    3725                 :             }
    3726                 : 
    3727             326 :             poBlock->DropLock();
    3728                 : 
    3729             326 :             if ( !pfnProgress(iSampleBlock
    3730                 :                               / ((double)(nBlocksPerRow*nBlocksPerColumn)),
    3731                 :                               "Compute Statistics", pProgressData) )
    3732                 :             {
    3733               0 :                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3734               0 :                 return CE_Failure;
    3735                 :             }
    3736                 :         }
    3737                 :     }
    3738                 : 
    3739              36 :     if( !pfnProgress( 1.0, "Compute Statistics", pProgressData ) )
    3740                 :     {
    3741               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3742               0 :         return CE_Failure;
    3743                 :     }
    3744                 : 
    3745                 : /* -------------------------------------------------------------------- */
    3746                 : /*      Save computed information.                                      */
    3747                 : /* -------------------------------------------------------------------- */
    3748              36 :     double dfMean = dfSum / nSampleCount;
    3749              36 :     double dfStdDev = sqrt((dfSum2 / nSampleCount) - (dfMean * dfMean));
    3750                 : 
    3751              36 :     if( nSampleCount > 1 )
    3752              36 :         SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
    3753                 : 
    3754                 : /* -------------------------------------------------------------------- */
    3755                 : /*      Record results.                                                 */
    3756                 : /* -------------------------------------------------------------------- */
    3757              36 :     if( pdfMin != NULL )
    3758              36 :         *pdfMin = dfMin;
    3759              36 :     if( pdfMax != NULL )
    3760              36 :         *pdfMax = dfMax;
    3761                 : 
    3762              36 :     if( pdfMean != NULL )
    3763              36 :         *pdfMean = dfMean;
    3764                 : 
    3765              36 :     if( pdfStdDev != NULL )
    3766              36 :         *pdfStdDev = dfStdDev;
    3767                 : 
    3768              36 :     if( nSampleCount > 0 )
    3769              36 :         return CE_None;
    3770                 :     else
    3771                 :     {
    3772                 :         CPLError( CE_Failure, CPLE_AppDefined,
    3773               0 :         "Failed to compute statistics, no valid pixels found in sampling." );
    3774               0 :         return CE_Failure;
    3775                 :     }
    3776                 : }
    3777                 : 
    3778                 : /************************************************************************/
    3779                 : /*                    GDALComputeRasterStatistics()                     */
    3780                 : /************************************************************************/
    3781                 : 
    3782                 : /**
    3783                 :   * \brief Compute image statistics. 
    3784                 :   *
    3785                 :   * @see GDALRasterBand::ComputeStatistics()
    3786                 :   */
    3787                 : 
    3788               0 : CPLErr CPL_STDCALL GDALComputeRasterStatistics( 
    3789                 :         GDALRasterBandH hBand, int bApproxOK, 
    3790                 :         double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev,
    3791                 :         GDALProgressFunc pfnProgress, void *pProgressData )
    3792                 : 
    3793                 : {
    3794               0 :     VALIDATE_POINTER1( hBand, "GDALComputeRasterStatistics", CE_Failure );
    3795                 : 
    3796               0 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    3797                 : 
    3798                 :     return poBand->ComputeStatistics( 
    3799                 :         bApproxOK, pdfMin, pdfMax, pdfMean, pdfStdDev,
    3800               0 :         pfnProgress, pProgressData );
    3801                 : }
    3802                 : 
    3803                 : /************************************************************************/
    3804                 : /*                           SetStatistics()                            */
    3805                 : /************************************************************************/
    3806                 : 
    3807                 : /**
    3808                 :  * \brief Set statistics on band.
    3809                 :  *
    3810                 :  * This method can be used to store min/max/mean/standard deviation
    3811                 :  * statistics on a raster band.  
    3812                 :  *
    3813                 :  * The default implementation stores them as metadata, and will only work 
    3814                 :  * on formats that can save arbitrary metadata.  This method cannot detect
    3815                 :  * whether metadata will be properly saved and so may return CE_None even
    3816                 :  * if the statistics will never be saved.
    3817                 :  *
    3818                 :  * This method is the same as the C function GDALSetRasterStatistics().
    3819                 :  * 
    3820                 :  * @param dfMin minimum pixel value.
    3821                 :  * 
    3822                 :  * @param dfMax maximum pixel value.
    3823                 :  *
    3824                 :  * @param dfMean mean (average) of all pixel values.    
    3825                 :  *
    3826                 :  * @param dfStdDev Standard deviation of all pixel values.
    3827                 :  *
    3828                 :  * @return CE_None on success or CE_Failure on failure. 
    3829                 :  */
    3830                 : 
    3831              62 : CPLErr GDALRasterBand::SetStatistics( double dfMin, double dfMax, 
    3832                 :                                       double dfMean, double dfStdDev )
    3833                 : 
    3834                 : {
    3835              62 :     char szValue[128] = { 0 };
    3836                 : 
    3837              62 :     sprintf( szValue, "%.14g", dfMin );
    3838              62 :     SetMetadataItem( "STATISTICS_MINIMUM", szValue );
    3839                 : 
    3840              62 :     sprintf( szValue, "%.14g", dfMax );
    3841              62 :     SetMetadataItem( "STATISTICS_MAXIMUM", szValue );
    3842                 : 
    3843              62 :     sprintf( szValue, "%.14g", dfMean );
    3844              62 :     SetMetadataItem( "STATISTICS_MEAN", szValue );
    3845                 : 
    3846              62 :     sprintf( szValue, "%.14g", dfStdDev );
    3847              62 :     SetMetadataItem( "STATISTICS_STDDEV", szValue );
    3848                 : 
    3849              62 :     return CE_None;
    3850                 : }
    3851                 : 
    3852                 : /************************************************************************/
    3853                 : /*                      GDALSetRasterStatistics()                       */
    3854                 : /************************************************************************/
    3855                 : 
    3856                 : /**
    3857                 :  * \brief Set statistics on band.
    3858                 :  *
    3859                 :  * @see GDALRasterBand::SetStatistics()
    3860                 :  */
    3861                 : 
    3862               0 : CPLErr CPL_STDCALL GDALSetRasterStatistics( 
    3863                 :         GDALRasterBandH hBand,  
    3864                 :         double dfMin, double dfMax, double dfMean, double dfStdDev )
    3865                 : 
    3866                 : {
    3867               0 :     VALIDATE_POINTER1( hBand, "GDALSetRasterStatistics", CE_Failure );
    3868                 : 
    3869               0 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    3870               0 :     return poBand->SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
    3871                 : }
    3872                 : 
    3873                 : /************************************************************************/
    3874                 : /*                        ComputeRasterMinMax()                         */
    3875                 : /************************************************************************/
    3876                 : 
    3877                 : /**
    3878                 :  * \brief Compute the min/max values for a band.
    3879                 :  * 
    3880                 :  * If approximate is OK, then the band's GetMinimum()/GetMaximum() will
    3881                 :  * be trusted.  If it doesn't work, a subsample of blocks will be read to
    3882                 :  * get an approximate min/max.  If the band has a nodata value it will
    3883                 :  * be excluded from the minimum and maximum.
    3884                 :  *
    3885                 :  * If bApprox is FALSE, then all pixels will be read and used to compute
    3886                 :  * an exact range.
    3887                 :  *
    3888                 :  * This method is the same as the C function GDALComputeRasterMinMax().
    3889                 :  * 
    3890                 :  * @param bApproxOK TRUE if an approximate (faster) answer is OK, otherwise
    3891                 :  * FALSE.
    3892                 :  * @param adfMinMax the array in which the minimum (adfMinMax[0]) and the
    3893                 :  * maximum (adfMinMax[1]) are returned.
    3894                 :  *
    3895                 :  * @return CE_None on success or CE_Failure on failure.
    3896                 :  */
    3897                 : 
    3898                 : 
    3899             781 : CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
    3900                 :                                             double adfMinMax[2] )
    3901                 : {
    3902             781 :     double  dfMin = 0.0;
    3903             781 :     double  dfMax = 0.0;
    3904                 : 
    3905                 : /* -------------------------------------------------------------------- */
    3906                 : /*      Does the driver already know the min/max?                       */
    3907                 : /* -------------------------------------------------------------------- */
    3908             781 :     if( bApproxOK )
    3909                 :     {
    3910                 :         int          bSuccessMin, bSuccessMax;
    3911                 : 
    3912               0 :         dfMin = GetMinimum( &bSuccessMin );
    3913               0 :         dfMax = GetMaximum( &bSuccessMax );
    3914                 : 
    3915               0 :         if( bSuccessMin && bSuccessMax )
    3916                 :         {
    3917               0 :             adfMinMax[0] = dfMin;
    3918               0 :             adfMinMax[1] = dfMax;
    3919               0 :             return CE_None;
    3920                 :         }
    3921                 :     }
    3922                 :     
    3923                 : /* -------------------------------------------------------------------- */
    3924                 : /*      If we have overview bands, use them for min/max.                */
    3925                 : /* -------------------------------------------------------------------- */
    3926             781 :     if ( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
    3927                 :     {
    3928                 :         GDALRasterBand *poBand;
    3929                 : 
    3930               0 :         poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
    3931                 : 
    3932               0 :         if ( poBand != this )
    3933               0 :             return poBand->ComputeRasterMinMax( FALSE, adfMinMax );
    3934                 :     }
    3935                 :     
    3936                 : /* -------------------------------------------------------------------- */
    3937                 : /*      Read actual data and compute minimum and maximum.               */
    3938                 : /* -------------------------------------------------------------------- */
    3939             781 :     int     bGotNoDataValue, bFirstValue = TRUE;
    3940                 :     double  dfNoDataValue;
    3941                 : 
    3942             781 :     dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
    3943                 : 
    3944             781 :     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
    3945             781 :     int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
    3946                 :     
    3947             781 :     if ( bApproxOK && HasArbitraryOverviews() )
    3948                 :     {
    3949                 : /* -------------------------------------------------------------------- */
    3950                 : /*      Figure out how much the image should be reduced to get an       */
    3951                 : /*      approximate value.                                              */
    3952                 : /* -------------------------------------------------------------------- */
    3953                 :         void    *pData;
    3954                 :         int     nXReduced, nYReduced;
    3955                 :         double  dfReduction = sqrt(
    3956               0 :             (double)nRasterXSize * nRasterYSize / GDALSTAT_APPROX_NUMSAMPLES );
    3957                 : 
    3958               0 :         if ( dfReduction > 1.0 )
    3959                 :         {
    3960               0 :             nXReduced = (int)( nRasterXSize / dfReduction );
    3961               0 :             nYReduced = (int)( nRasterYSize / dfReduction );
    3962                 : 
    3963                 :             // Catch the case of huge resizing ratios here
    3964               0 :             if ( nXReduced == 0 )
    3965               0 :                 nXReduced = 1;
    3966               0 :             if ( nYReduced == 0 )
    3967               0 :                 nYReduced = 1;
    3968                 :         }
    3969                 :         else
    3970                 :         {
    3971               0 :             nXReduced = nRasterXSize;
    3972               0 :             nYReduced = nRasterYSize;
    3973                 :         }
    3974                 : 
    3975                 :         pData =
    3976               0 :             CPLMalloc(GDALGetDataTypeSize(eDataType)/8 * nXReduced * nYReduced);
    3977                 : 
    3978                 :         CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
    3979               0 :                    nXReduced, nYReduced, eDataType, 0, 0 );
    3980               0 :         if ( eErr != CE_None )
    3981                 :         {
    3982               0 :             CPLFree(pData);
    3983               0 :             return eErr;
    3984                 :         }
    3985                 :         
    3986                 :         /* this isn't the fastest way to do this, but is easier for now */
    3987               0 :         for( int iY = 0; iY < nYReduced; iY++ )
    3988                 :         {
    3989               0 :             for( int iX = 0; iX < nXReduced; iX++ )
    3990                 :             {
    3991               0 :                 int    iOffset = iX + iY * nXReduced;
    3992               0 :                 double dfValue = 0.0;
    3993                 : 
    3994               0 :                 switch( eDataType )
    3995                 :                 {
    3996                 :                   case GDT_Byte:
    3997                 :                   {
    3998               0 :                     if (bSignedByte)
    3999               0 :                         dfValue = ((signed char *)pData)[iOffset];
    4000                 :                     else
    4001               0 :                         dfValue = ((GByte *)pData)[iOffset];
    4002               0 :                     break;
    4003                 :                   }
    4004                 :                   case GDT_UInt16:
    4005               0 :                     dfValue = ((GUInt16 *)pData)[iOffset];
    4006               0 :                     break;
    4007                 :                   case GDT_Int16:
    4008               0 :                     dfValue = ((GInt16 *)pData)[iOffset];
    4009               0 :                     break;
    4010                 :                   case GDT_UInt32:
    4011               0 :                     dfValue = ((GUInt32 *)pData)[iOffset];
    4012               0 :                     break;
    4013                 :                   case GDT_Int32:
    4014               0 :                     dfValue = ((GInt32 *)pData)[iOffset];
    4015               0 :                     break;
    4016                 :                   case GDT_Float32:
    4017               0 :                     dfValue = ((float *)pData)[iOffset];
    4018               0 :                     if (CPLIsNan(dfValue))
    4019               0 :                         continue;
    4020               0 :                     break;
    4021                 :                   case GDT_Float64:
    4022               0 :                     dfValue = ((double *)pData)[iOffset];
    4023               0 :                     if (CPLIsNan(dfValue))
    4024               0 :                         continue;
    4025               0 :                     break;
    4026                 :                   case GDT_CInt16:
    4027               0 :                     dfValue = ((GInt16 *)pData)[iOffset*2];
    4028               0 :                     break;
    4029                 :                   case GDT_CInt32:
    4030               0 :                     dfValue = ((GInt32 *)pData)[iOffset*2];
    4031               0 :                     break;
    4032                 :                   case GDT_CFloat32:
    4033               0 :                     dfValue = ((float *)pData)[iOffset*2];
    4034               0 :                     if( CPLIsNan(dfValue) )
    4035               0 :                         continue;
    4036               0 :                     break;
    4037                 :                   case GDT_CFloat64:
    4038               0 :                     dfValue = ((double *)pData)[iOffset*2];
    4039               0 :                     if( CPLIsNan(dfValue) )
    4040               0 :                         continue;
    4041                 :                     break;
    4042                 :                   default:
    4043                 :                     CPLAssert( FALSE );
    4044                 :                 }
    4045                 :                 
    4046               0 :                 if( bGotNoDataValue && dfValue == dfNoDataValue )
    4047               0 :                     continue;
    4048                 : 
    4049               0 :                 if( bFirstValue )
    4050                 :                 {
    4051               0 :                     dfMin = dfMax = dfValue;
    4052               0 :                     bFirstValue = FALSE;
    4053                 :                 }
    4054                 :                 else
    4055                 :                 {
    4056               0 :                     dfMin = MIN(dfMin,dfValue);
    4057               0 :                     dfMax = MAX(dfMax,dfValue);
    4058                 :                 }
    4059                 :             }
    4060                 :         }
    4061                 : 
    4062               0 :         CPLFree( pData );
    4063                 :     }
    4064                 : 
    4065                 :     else    // No arbitrary overviews
    4066                 :     {
    4067                 :         int     nSampleRate;
    4068                 : 
    4069             781 :         if( !InitBlockInfo() )
    4070               0 :             return CE_Failure;
    4071                 : 
    4072                 : /* -------------------------------------------------------------------- */
    4073                 : /*      Figure out the ratio of blocks we will read to get an           */
    4074                 : /*      approximate value.                                              */
    4075                 : /* -------------------------------------------------------------------- */
    4076             781 :         if ( bApproxOK )
    4077                 :         {
    4078                 :             nSampleRate = 
    4079               0 :                 (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn));
    4080                 :         }
    4081                 :         else
    4082             781 :             nSampleRate = 1;
    4083                 :         
    4084           15362 :         for( int iSampleBlock = 0; 
    4085                 :              iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
    4086                 :              iSampleBlock += nSampleRate )
    4087                 :         {
    4088                 :             int  iXBlock, iYBlock, nXCheck, nYCheck;
    4089                 :             GDALRasterBlock *poBlock;
    4090                 :             void* pData;
    4091                 : 
    4092           14581 :             iYBlock = iSampleBlock / nBlocksPerRow;
    4093           14581 :             iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
    4094                 :             
    4095           14581 :             poBlock = GetLockedBlockRef( iXBlock, iYBlock );
    4096           14581 :             if( poBlock == NULL )
    4097               0 :                 continue;
    4098           14581 :             if( poBlock->GetDataRef() == NULL )
    4099                 :             {
    4100               0 :                 poBlock->DropLock();
    4101               0 :                 continue;
    4102                 :             }
    4103                 :             
    4104           14581 :             pData = poBlock->GetDataRef();
    4105                 :             
    4106           14581 :             if( (iXBlock+1) * nBlockXSize > GetXSize() )
    4107             144 :                 nXCheck = GetXSize() - iXBlock * nBlockXSize;
    4108                 :             else
    4109           14437 :                 nXCheck = nBlockXSize;
    4110                 : 
    4111           14581 :             if( (iYBlock+1) * nBlockYSize > GetYSize() )
    4112             178 :                 nYCheck = GetYSize() - iYBlock * nBlockYSize;
    4113                 :             else
    4114           14403 :                 nYCheck = nBlockYSize;
    4115                 :                 
    4116                 :             /* this isn't the fastest way to do this, but is easier for now */
    4117          164389 :             for( int iY = 0; iY < nYCheck; iY++ )
    4118                 :             {
    4119         5054620 :                 for( int iX = 0; iX < nXCheck; iX++ )
    4120                 :                 {
    4121         4904812 :                     int    iOffset = iX + iY * nBlockXSize;
    4122         4904812 :                     double dfValue = 0.0;
    4123                 : 
    4124         4904812 :                     switch( eDataType )
    4125                 :                     {
    4126                 :                       case GDT_Byte:
    4127                 :                       {
    4128         2859585 :                         if (bSignedByte)
    4129               0 :                             dfValue = ((signed char *) pData)[iOffset];
    4130                 :                         else
    4131         2859585 :                             dfValue = ((GByte *) pData)[iOffset];
    4132         2859585 :                         break;
    4133                 :                       }
    4134                 :                       case GDT_UInt16:
    4135           34900 :                         dfValue = ((GUInt16 *) pData)[iOffset];
    4136           34900 :                         break;
    4137                 :                       case GDT_Int16:
    4138         1728853 :                         dfValue = ((GInt16 *) pData)[iOffset];
    4139         1728853 :                         break;
    4140                 :                       case GDT_UInt32:
    4141           16900 :                         dfValue = ((GUInt32 *) pData)[iOffset];
    4142           16900 :                         break;
    4143                 :                       case GDT_Int32:
    4144           53870 :                         dfValue = ((GInt32 *) pData)[iOffset];
    4145           53870 :                         break;
    4146                 :                       case GDT_Float32:
    4147          159704 :                         dfValue = ((float *) pData)[iOffset];
    4148          159704 :                         if( CPLIsNan(dfValue) )
    4149               0 :                             continue;
    4150          159704 :                         break;
    4151                 :                       case GDT_Float64:
    4152           26600 :                         dfValue = ((double *) pData)[iOffset];
    4153           26600 :                         if( CPLIsNan(dfValue) )
    4154               0 :                             continue;
    4155           26600 :                         break;
    4156                 :                       case GDT_CInt16:
    4157            4000 :                         dfValue = ((GInt16 *) pData)[iOffset*2];
    4158            4000 :                         break;
    4159                 :                       case GDT_CInt32:
    4160            4000 :                         dfValue = ((GInt32 *) pData)[iOffset*2];
    4161            4000 :                         break;
    4162                 :                       case GDT_CFloat32:
    4163            8000 :                         dfValue = ((float *) pData)[iOffset*2];
    4164            8000 :                         if( CPLIsNan(dfValue) )
    4165               0 :                             continue;
    4166            8000 :                         break;
    4167                 :                       case GDT_CFloat64:
    4168            8400 :                         dfValue = ((double *) pData)[iOffset*2];
    4169            8400 :                         if( CPLIsNan(dfValue) )
    4170               0 :                             continue;
    4171                 :                         break;
    4172                 :                       default:
    4173                 :                         CPLAssert( FALSE );
    4174                 :                     }
    4175                 :                     
    4176         4904812 :                     if( bGotNoDataValue && dfValue == dfNoDataValue )
    4177          333763 :                         continue;
    4178                 : 
    4179         4571049 :                     if( bFirstValue )
    4180                 :                     {
    4181             781 :                         dfMin = dfMax = dfValue;
    4182             781 :                         bFirstValue = FALSE;
    4183                 :                     }
    4184                 :                     else
    4185                 :                     {
    4186         4570268 :                         dfMin = MIN(dfMin,dfValue);
    4187         4570268 :                         dfMax = MAX(dfMax,dfValue);
    4188                 :                     }
    4189                 :                 }
    4190                 :             }
    4191                 : 
    4192           14581 :             poBlock->DropLock();
    4193                 :         }
    4194                 :     }
    4195                 : 
    4196             781 :     adfMinMax[0] = dfMin;
    4197             781 :     adfMinMax[1] = dfMax;
    4198                 : 
    4199             781 :     if (bFirstValue)
    4200                 :     {
    4201                 :         CPLError( CE_Failure, CPLE_AppDefined,
    4202               0 :             "Failed to compute min/max, no valid pixels found in sampling." );
    4203               0 :         return CE_Failure;
    4204                 :     }
    4205                 :     else
    4206                 :     {
    4207             781 :         return CE_None;
    4208                 :     }
    4209                 : }
    4210                 : 
    4211                 : /************************************************************************/
    4212                 : /*                      GDALComputeRasterMinMax()                       */
    4213                 : /************************************************************************/
    4214                 : 
    4215                 : /**
    4216                 :  * \brief Compute the min/max values for a band.
    4217                 :  * 
    4218                 :  * @see GDALRasterBand::ComputeRasterMinMax()
    4219                 :  */
    4220                 : 
    4221                 : void CPL_STDCALL 
    4222             781 : GDALComputeRasterMinMax( GDALRasterBandH hBand, int bApproxOK, 
    4223                 :                          double adfMinMax[2] )
    4224                 : 
    4225                 : {
    4226             781 :     VALIDATE_POINTER0( hBand, "GDALComputeRasterMinMax" );
    4227                 : 
    4228             781 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    4229             781 :     poBand->ComputeRasterMinMax( bApproxOK, adfMinMax );
    4230                 : }
    4231                 : 
    4232                 : /************************************************************************/
    4233                 : /*                        SetDefaultHistogram()                         */
    4234                 : /************************************************************************/
    4235                 : 
    4236                 : /* FIXME : add proper documentation */
    4237                 : /**
    4238                 :  * \brief Set default histogram.
    4239                 :  */
    4240               0 : CPLErr GDALRasterBand::SetDefaultHistogram( double dfMin, double dfMax, 
    4241                 :                                             int nBuckets, int *panHistogram )
    4242                 : 
    4243                 : {
    4244               0 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    4245                 :         CPLError( CE_Failure, CPLE_NotSupported,
    4246               0 :                   "SetDefaultHistogram() not implemented for this format." );
    4247                 : 
    4248               0 :     return CE_Failure;
    4249                 : }
    4250                 : 
    4251                 : /************************************************************************/
    4252                 : /*                      GDALSetDefaultHistogram()                       */
    4253                 : /************************************************************************/
    4254                 : 
    4255                 : /**
    4256                 :  * \brief Set default histogram.
    4257                 :  *
    4258                 :  * @see GDALRasterBand::SetDefaultHistogram()
    4259                 :  */
    4260                 : 
    4261               0 : CPLErr CPL_STDCALL GDALSetDefaultHistogram( GDALRasterBandH hBand, 
    4262                 :                                             double dfMin, double dfMax, 
    4263                 :                                             int nBuckets, int *panHistogram )
    4264                 : 
    4265                 : {
    4266               0 :     VALIDATE_POINTER1( hBand, "GDALSetDefaultHistogram", CE_Failure );
    4267                 : 
    4268               0 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    4269               0 :     return poBand->SetDefaultHistogram( dfMin, dfMax, nBuckets, panHistogram );
    4270                 : }
    4271                 : 
    4272                 : /************************************************************************/
    4273                 : /*                           GetDefaultRAT()                            */
    4274                 : /************************************************************************/
    4275                 : 
    4276                 : /**
    4277                 :  * \brief Fetch default Raster Attribute Table.
    4278                 :  *
    4279                 :  * A RAT will be returned if there is a default one associated with the
    4280                 :  * band, otherwise NULL is returned.  The returned RAT is owned by the
    4281                 :  * band and should not be deleted, or altered by the application. 
    4282                 :  * 
    4283                 :  * @return NULL, or a pointer to an internal RAT owned by the band.
    4284                 :  */
    4285                 : 
    4286              84 : const GDALRasterAttributeTable *GDALRasterBand::GetDefaultRAT()
    4287                 : 
    4288                 : {
    4289              84 :     return NULL;
    4290                 : }
    4291                 : 
    4292                 : /************************************************************************/
    4293                 : /*                         GDALGetDefaultRAT()                          */
    4294                 : /************************************************************************/
    4295                 : 
    4296                 : /**
    4297                 :  * \brief Fetch default Raster Attribute Table.
    4298                 :  *
    4299                 :  * @see GDALRasterBand::GetDefaultRAT()
    4300                 :  */
    4301                 : 
    4302              13 : GDALRasterAttributeTableH CPL_STDCALL GDALGetDefaultRAT( GDALRasterBandH hBand)
    4303                 : 
    4304                 : {
    4305              13 :     VALIDATE_POINTER1( hBand, "GDALGetDefaultRAT", NULL );
    4306                 : 
    4307              13 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    4308              13 :     return (GDALRasterAttributeTableH) poBand->GetDefaultRAT();
    4309                 : }
    4310                 : 
    4311                 : /************************************************************************/
    4312                 : /*                           SetDefaultRAT()                            */
    4313                 : /************************************************************************/
    4314                 : 
    4315                 : /**
    4316                 :  * \brief Set default Raster Attribute Table.
    4317                 :  *
    4318                 :  * Associates a default RAT with the band.  If not implemented for the
    4319                 :  * format a CPLE_NotSupported error will be issued.  If successful a copy
    4320                 :  * of the RAT is made, the original remains owned by the caller.
    4321                 :  *
    4322                 :  * @param poRAT the RAT to assign to the band.
    4323                 :  *
    4324                 :  * @return CE_None on success or CE_Failure if unsupported or otherwise 
    4325                 :  * failing.
    4326                 :  */
    4327                 : 
    4328               0 : CPLErr GDALRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
    4329                 : 
    4330                 : {
    4331               0 :     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
    4332                 :         CPLError( CE_Failure, CPLE_NotSupported,
    4333               0 :                   "SetDefaultRAT() not implemented for this format." );
    4334                 : 
    4335               0 :     return CE_Failure;
    4336                 : }
    4337                 : 
    4338                 : /************************************************************************/
    4339                 : /*                         GDALSetDefaultRAT()                          */
    4340                 : /************************************************************************/
    4341                 : 
    4342                 : /**
    4343                 :  * \brief Set default Raster Attribute Table.
    4344                 :  *
    4345                 :  * @see GDALRasterBand::GDALSetDefaultRAT()
    4346                 :  */
    4347                 : 
    4348               1 : CPLErr CPL_STDCALL GDALSetDefaultRAT( GDALRasterBandH hBand,
    4349                 :                                       GDALRasterAttributeTableH hRAT )
    4350                 : 
    4351                 : {
    4352               1 :     VALIDATE_POINTER1( hBand, "GDALSetDefaultRAT", CE_Failure );
    4353               1 :     VALIDATE_POINTER1( hRAT, "GDALSetDefaultRAT", CE_Failure );
    4354                 : 
    4355               1 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    4356                 : 
    4357                 :     return poBand->SetDefaultRAT( 
    4358               1 :         static_cast<GDALRasterAttributeTable *>(hRAT) );
    4359                 : }
    4360                 : 
    4361                 : /************************************************************************/
    4362                 : /*                            GetMaskBand()                             */
    4363                 : /************************************************************************/
    4364                 : 
    4365                 : /**
    4366                 :  * \brief Return the mask band associated with the band.
    4367                 :  *
    4368                 :  * The GDALRasterBand class includes a default implementation of GetMaskBand() that
    4369                 :  * returns one of four default implementations :
    4370                 :  * <ul>
    4371                 :  * <li>If a corresponding .msk file exists it will be used for the mask band.</li>
    4372                 :  * <li>If the dataset has a NODATA_VALUES metadata item, an instance of the
    4373                 :  *     new GDALNoDataValuesMaskBand class will be returned.
    4374                 :  *     GetMaskFlags() will return GMF_NODATA | GMF_PER_DATASET. @since GDAL 1.6.0</li>
    4375                 :  * <li>If the band has a nodata value set, an instance of the new
    4376                 :  *     GDALNodataMaskRasterBand class will be returned.
    4377                 :  *     GetMaskFlags() will return GMF_NODATA.</li>
    4378                 :  * <li>If there is no nodata value, but the dataset has an alpha band that seems
    4379                 :  *     to apply to this band (specific rules yet to be determined) and that is
    4380                 :  *     of type GDT_Byte then that alpha band will be returned, and the flags
    4381                 :  *     GMF_PER_DATASET and GMF_ALPHA will be returned in the flags.</li>
    4382                 :  * <li>If neither of the above apply, an instance of the new GDALAllValidRasterBand
    4383                 :  *     class will be returned that has 255 values for all pixels.
    4384                 :  *     The null flags will return GMF_ALL_VALID.</li>
    4385                 :  * </ul>
    4386                 :  *
    4387                 :  * Note that the GetMaskBand() should always return a GDALRasterBand mask, even if it is only
    4388                 :  * an all 255 mask with the flags indicating GMF_ALL_VALID. 
    4389                 :  *
    4390                 :  * @return a valid mask band.
    4391                 :  *
    4392                 :  * @since GDAL 1.5.0
    4393                 :  *
    4394                 :  * @see http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask
    4395                 :  *
    4396                 :  */
    4397             574 : GDALRasterBand *GDALRasterBand::GetMaskBand()
    4398                 : 
    4399                 : {
    4400             574 :     if( poMask != NULL )
    4401              79 :         return poMask;
    4402                 : 
    4403                 : /* -------------------------------------------------------------------- */
    4404                 : /*      Check for a mask in a .msk file.                                */
    4405                 : /* -------------------------------------------------------------------- */
    4406             495 :     GDALDataset *poDS = GetDataset();
    4407                 : 
    4408             495 :     if( poDS != NULL && poDS->oOvManager.HaveMaskFile() )
    4409                 :     {
    4410               8 :         poMask = poDS->oOvManager.GetMaskBand( nBand );
    4411               8 :         if( poMask != NULL )
    4412                 :         {
    4413               8 :             nMaskFlags = poDS->oOvManager.GetMaskFlags( nBand );
    4414               8 :             return poMask;
    4415                 :         }
    4416                 :     }
    4417                 : 
    4418                 : /* -------------------------------------------------------------------- */
    4419                 : /*      Check for NODATA_VALUES metadata.                               */
    4420                 : /* -------------------------------------------------------------------- */
    4421             487 :     if (poDS != NULL)
    4422                 :     {
    4423             487 :         const char* pszNoDataValues = poDS->GetMetadataItem("NODATA_VALUES");
    4424             487 :         if (pszNoDataValues != NULL)
    4425                 :         {
    4426              41 :             char** papszNoDataValues = CSLTokenizeStringComplex(pszNoDataValues, " ", FALSE, FALSE);
    4427                 : 
    4428                 :             /* Make sure we have as many values as bands */
    4429              41 :             if (CSLCount(papszNoDataValues) == poDS->GetRasterCount() && poDS->GetRasterCount() != 0)
    4430                 :             {
    4431              41 :                 CSLDestroy(papszNoDataValues);
    4432                 : 
    4433                 :                 /* Make sure that all bands have the same data type */
    4434                 :                 /* This is cleraly not a fundamental condition, just a condition to make implementation */
    4435                 :                 /* easier. */
    4436                 :                 int i;
    4437              41 :                 GDALDataType eDT = GDT_Unknown;
    4438             164 :                 for(i=0;i<poDS->GetRasterCount();i++)
    4439                 :                 {
    4440             123 :                     if (i == 0)
    4441              41 :                         eDT = poDS->GetRasterBand(1)->GetRasterDataType();
    4442              82 :                     else if (eDT != poDS->GetRasterBand(i + 1)->GetRasterDataType())
    4443                 :                     {
    4444               0 :                         break;
    4445                 :                     }
    4446                 :                 }
    4447              41 :                 if (i == poDS->GetRasterCount())
    4448                 :                 {
    4449              41 :                     nMaskFlags = GMF_NODATA | GMF_PER_DATASET;
    4450              41 :                     poMask = new GDALNoDataValuesMaskBand ( poDS );
    4451              41 :                     bOwnMask = true;
    4452              41 :                     return poMask;
    4453                 :                 }
    4454                 :                 else
    4455                 :                 {
    4456                 :                     CPLError(CE_Warning, CPLE_AppDefined,
    4457               0 :                             "All bands should have the same type in order the NODATA_VALUES metadata item to be used as a mask.");
    4458                 :                 }
    4459                 :             }
    4460                 :             else
    4461                 :             {
    4462                 :                 CPLError(CE_Warning, CPLE_AppDefined,
    4463                 :                         "NODATA_VALUES metadata item doesn't have the same number of values as the number of bands.\n"
    4464               0 :                         "Ignoring it for mask.");
    4465                 :             }
    4466                 : 
    4467               0 :             CSLDestroy(papszNoDataValues);
    4468                 :         }
    4469                 :     }
    4470                 : 
    4471                 : /* -------------------------------------------------------------------- */
    4472                 : /*      Check for nodata case.                                          */
    4473                 : /* -------------------------------------------------------------------- */
    4474                 :     int bHaveNoData;
    4475                 : 
    4476             446 :     GetNoDataValue( &bHaveNoData );
    4477                 :     
    4478             446 :     if( bHaveNoData )
    4479                 :     {
    4480              69 :         nMaskFlags = GMF_NODATA;
    4481              69 :         poMask = new GDALNoDataMaskBand( this );
    4482              69 :         bOwnMask = true;
    4483              69 :         return poMask;
    4484                 :     }
    4485                 : 
    4486                 : /* -------------------------------------------------------------------- */
    4487                 : /*      Check for alpha case.                                           */
    4488                 : /* -------------------------------------------------------------------- */
    4489             386 :     if( poDS != NULL 
    4490                 :         && poDS->GetRasterCount() == 2
    4491                 :         && this == poDS->GetRasterBand(1)
    4492               9 :         && poDS->GetRasterBand(2)->GetColorInterpretation() == GCI_AlphaBand
    4493                 :         && poDS->GetRasterBand(2)->GetRasterDataType() == GDT_Byte )
    4494                 :     {
    4495               2 :         nMaskFlags = GMF_ALPHA | GMF_PER_DATASET;
    4496               2 :         poMask = poDS->GetRasterBand(2);
    4497               2 :         return poMask;
    4498                 :     }
    4499                 : 
    4500             405 :     if( poDS != NULL 
    4501                 :         && poDS->GetRasterCount() == 4
    4502                 :         && (this == poDS->GetRasterBand(1)
    4503                 :             || this == poDS->GetRasterBand(2)
    4504                 :             || this == poDS->GetRasterBand(3))
    4505              30 :         && poDS->GetRasterBand(4)->GetColorInterpretation() == GCI_AlphaBand
    4506                 :         && poDS->GetRasterBand(4)->GetRasterDataType() == GDT_Byte )
    4507                 :     {
    4508              15 :         nMaskFlags = GMF_ALPHA | GMF_PER_DATASET;
    4509              15 :         poMask = poDS->GetRasterBand(4);
    4510              15 :         return poMask;
    4511                 :     }
    4512                 : 
    4513                 : /* -------------------------------------------------------------------- */
    4514                 : /*      Fallback to all valid case.                                     */
    4515                 : /* -------------------------------------------------------------------- */
    4516             360 :     nMaskFlags = GMF_ALL_VALID;
    4517             360 :     poMask = new GDALAllValidMaskBand( this );
    4518             360 :     bOwnMask = true;
    4519                 : 
    4520             360 :     return poMask;
    4521                 : }
    4522                 : 
    4523                 : /************************************************************************/
    4524                 : /*                          GDALGetMaskBand()                           */
    4525                 : /************************************************************************/
    4526                 : 
    4527                 : /**
    4528                 :  * \brief Return the mask band associated with the band.
    4529                 :  *
    4530                 :  * @see GDALRasterBand::GetMaskBand()
    4531                 :  */
    4532                 : 
    4533              77 : GDALRasterBandH CPL_STDCALL GDALGetMaskBand( GDALRasterBandH hBand )
    4534                 : 
    4535                 : {
    4536              77 :     VALIDATE_POINTER1( hBand, "GDALGetMaskBand", NULL );
    4537                 : 
    4538              77 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    4539              77 :     return poBand->GetMaskBand();
    4540                 : }
    4541                 : 
    4542                 : /************************************************************************/
    4543                 : /*                            GetMaskFlags()                            */
    4544                 : /************************************************************************/
    4545                 : 
    4546                 : /**
    4547                 :  * \brief Return the status flags of the mask band associated with the band.
    4548                 :  *
    4549                 :  * The GetMaskFlags() method returns an bitwise OR-ed set of status flags with
    4550                 :  * the following available definitions that may be extended in the future:
    4551                 :  * <ul>
    4552                 :  * <li>GMF_ALL_VALID(0x01): There are no invalid pixels, all mask values will be 255.
    4553                 :  *     When used this will normally be the only flag set.</li>
    4554                 :  * <li>GMF_PER_DATASET(0x02): The mask band is shared between all bands on the dataset.</li>
    4555                 :  * <li>GMF_ALPHA(0x04): The mask band is actually an alpha band and may have values
    4556                 :  *     other than 0 and 255.</li>
    4557                 :  * <li>GMF_NODATA(0x08): Indicates the mask is actually being generated from nodata values.
    4558                 :  *     (mutually exclusive of GMF_ALPHA)</li>
    4559                 :  * </ul>
    4560                 :  *
    4561                 :  * The GDALRasterBand class includes a default implementation of GetMaskBand() that
    4562                 :  * returns one of four default implementations :
    4563                 :  * <ul>
    4564                 :  * <li>If a corresponding .msk file exists it will be used for the mask band.</li>
    4565                 :  * <li>If the dataset has a NODATA_VALUES metadata item, an instance of the
    4566                 :  *     new GDALNoDataValuesMaskBand class will be returned.
    4567                 :  *     GetMaskFlags() will return GMF_NODATA | GMF_PER_DATASET. @since GDAL 1.6.0</li>
    4568                 :  * <li>If the band has a nodata value set, an instance of the new
    4569                 :  *     GDALNodataMaskRasterBand class will be returned.
    4570                 :  *     GetMaskFlags() will return GMF_NODATA.</li>
    4571                 :  * <li>If there is no nodata value, but the dataset has an alpha band that seems
    4572                 :  *     to apply to this band (specific rules yet to be determined) and that is
    4573                 :  *     of type GDT_Byte then that alpha band will be returned, and the flags
    4574                 :  *     GMF_PER_DATASET and GMF_ALPHA will be returned in the flags.</li>
    4575                 :  * <li>If neither of the above apply, an instance of the new GDALAllValidRasterBand
    4576                 :  *     class will be returned that has 255 values for all pixels.
    4577                 :  *     The null flags will return GMF_ALL_VALID.</li>
    4578                 :  * </ul>
    4579                 :  *
    4580                 :  * @since GDAL 1.5.0
    4581                 :  *
    4582                 :  * @return a valid mask band.
    4583                 :  *
    4584                 :  * @see http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask
    4585                 :  *
    4586                 :  */
    4587            1502 : int GDALRasterBand::GetMaskFlags()
    4588                 : 
    4589                 : {
    4590                 :     // If we don't have a band yet, force this now so that the masks value
    4591                 :     // will be initialized.
    4592                 : 
    4593            1502 :     if( poMask == NULL )
    4594             483 :         GetMaskBand();
    4595                 : 
    4596            1502 :     return nMaskFlags;
    4597                 : }
    4598                 : 
    4599                 : /************************************************************************/
    4600                 : /*                          GDALGetMaskFlags()                          */
    4601                 : /************************************************************************/
    4602                 : 
    4603                 : /**
    4604                 :  * \brief Return the status flags of the mask band associated with the band.
    4605                 :  *
    4606                 :  * @see GDALRasterBand::GetMaskFlags()
    4607                 :  */
    4608                 : 
    4609              66 : int CPL_STDCALL GDALGetMaskFlags( GDALRasterBandH hBand )
    4610                 : 
    4611                 : {
    4612              66 :     VALIDATE_POINTER1( hBand, "GDALGetMaskFlags", GMF_ALL_VALID );
    4613                 : 
    4614              66 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    4615              66 :     return poBand->GetMaskFlags();
    4616                 : }
    4617                 : 
    4618                 : /************************************************************************/
    4619                 : /*                           CreateMaskBand()                           */
    4620                 : /************************************************************************/
    4621                 : 
    4622                 : /**
    4623                 :  * \brief Adds a mask band to the current band
    4624                 :  *
    4625                 :  * The default implementation of the CreateMaskBand() method is implemented
    4626                 :  * based on similar rules to the .ovr handling implemented using the
    4627                 :  * GDALDefaultOverviews object. A TIFF file with the extension .msk will
    4628                 :  * be created with the same basename as the original file, and it will have
    4629                 :  * as many bands as the original image (or just one for GMF_PER_DATASET).
    4630                 :  * The mask images will be deflate compressed tiled images with the same
    4631                 :  * block size as the original image if possible.
    4632                 :  *
    4633                 :  * @since GDAL 1.5.0
    4634                 :  *
    4635                 :  * @return CE_None on success or CE_Failure on an error.
    4636                 :  *
    4637                 :  * @see http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask
    4638                 :  *
    4639                 :  */
    4640                 : 
    4641               0 : CPLErr GDALRasterBand::CreateMaskBand( int nFlags )
    4642                 : 
    4643                 : {
    4644               0 :     if( poDS != NULL && poDS->oOvManager.IsInitialized() )
    4645               0 :         return poDS->oOvManager.CreateMaskBand( nFlags, nBand );
    4646                 : 
    4647                 :     CPLError( CE_Failure, CPLE_NotSupported,
    4648               0 :               "CreateMaskBand() not supported for this band." );
    4649                 :     
    4650               0 :     return CE_Failure;
    4651                 : }
    4652                 : 
    4653                 : /************************************************************************/
    4654                 : /*                         GDALCreateMaskBand()                         */
    4655                 : /************************************************************************/
    4656                 : 
    4657                 : /**
    4658                 :  * \brief Adds a mask band to the current band
    4659                 :  *
    4660                 :  * @see GDALRasterBand::CreateMaskBand()
    4661                 :  */
    4662                 : 
    4663               6 : CPLErr CPL_STDCALL GDALCreateMaskBand( GDALRasterBandH hBand, int nFlags )
    4664                 : 
    4665                 : {
    4666               6 :     VALIDATE_POINTER1( hBand, "GDALCreateMaskBand", CE_Failure );
    4667                 : 
    4668               6 :     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
    4669               6 :     return poBand->CreateMaskBand( nFlags );
    4670                 : }
    4671                 : 
    4672                 : /************************************************************************/
    4673                 : /*                    GetIndexColorTranslationTo()                      */
    4674                 : /************************************************************************/
    4675                 : 
    4676                 : /**
    4677                 :  * \brief Compute translation table for color tables.
    4678                 :  *
    4679                 :  * When the raster band has a palette index, it may be usefull to compute
    4680                 :  * the "translation" of this palette to the palette of another band.
    4681                 :  * The translation tries to do exact matching first, and then approximate
    4682                 :  * matching if no exact matching is possible.
    4683                 :  * This method returns a table such that table[i] = j where i is an index
    4684                 :  * of the 'this' rasterband and j the corresponding index for the reference
    4685                 :  * rasterband.
    4686                 :  *
    4687                 :  * This method is thought as internal to GDAL and is used for drivers
    4688                 :  * like RPFTOC.
    4689                 :  *
    4690                 :  * The implementation only supports 1-byte palette rasterbands.
    4691                 :  *
    4692                 :  * @param poReferenceBand the raster band
    4693                 :  * @param pTranslationTable an already allocated translation table (at least 256 bytes),
    4694                 :  *                          or NULL to let the method allocate it
    4695                 :  * @param poApproximateMatching a pointer to a flag that is set if the matching
    4696                 :  *                              is approximate. May be NULL.
    4697                 :  *
    4698                 :  * @return a translation table if the two bands are palette index and that they do
    4699                 :  *         not match or NULL in other cases.
    4700                 :  *         The table must be freed with CPLFree if NULL was passed for pTranslationTable.
    4701                 :  */
    4702                 : 
    4703               3 : unsigned char* GDALRasterBand::GetIndexColorTranslationTo(GDALRasterBand* poReferenceBand,
    4704                 :                                                           unsigned char* pTranslationTable,
    4705                 :                                                           int* pApproximateMatching )
    4706                 : {
    4707               3 :     if (poReferenceBand == NULL)
    4708               0 :         return NULL;
    4709                 : 
    4710               6 :     if (poReferenceBand->GetColorInterpretation() == GCI_PaletteIndex &&
    4711               3 :         GetColorInterpretation() == GCI_PaletteIndex &&
    4712                 :         poReferenceBand->GetRasterDataType() == GDT_Byte &&
    4713                 :         GetRasterDataType() == GDT_Byte)
    4714                 :     {
    4715               3 :         GDALColorTable* srcColorTable = GetColorTable();
    4716               3 :         GDALColorTable* destColorTable = poReferenceBand->GetColorTable();
    4717               3 :         if (srcColorTable != NULL && destColorTable != NULL)
    4718                 :         {
    4719               3 :             int nEntries = srcColorTable->GetColorEntryCount();
    4720               3 :             int nRefEntries = destColorTable->GetColorEntryCount();
    4721                 :             int bHasNoDataValueSrc;
    4722               3 :             int noDataValueSrc = (int)GetNoDataValue(&bHasNoDataValueSrc);
    4723                 :             int bHasNoDataValueRef;
    4724               3 :             int noDataValueRef = (int)poReferenceBand->GetNoDataValue(&bHasNoDataValueRef);
    4725                 :             int samePalette;
    4726                 :             int i, j;
    4727                 : 
    4728               3 :             if (pApproximateMatching)
    4729               2 :                 *pApproximateMatching = FALSE;
    4730                 : 
    4731               6 :             if (nEntries == nRefEntries && bHasNoDataValueSrc == bHasNoDataValueRef &&
    4732                 :                 (bHasNoDataValueSrc == FALSE || noDataValueSrc == noDataValueRef))
    4733                 :             {
    4734               3 :                 samePalette = TRUE;
    4735             693 :                 for(i=0;i<nEntries;i++)
    4736                 :                 {
    4737             690 :                     if (noDataValueSrc == i)
    4738               2 :                         continue;
    4739             688 :                     const GDALColorEntry* entry = srcColorTable->GetColorEntry(i);
    4740             688 :                     const GDALColorEntry* entryRef = destColorTable->GetColorEntry(i);
    4741             688 :                     if (entry->c1 != entryRef->c1 ||
    4742                 :                         entry->c2 != entryRef->c2 ||
    4743                 :                         entry->c3 != entryRef->c3)
    4744                 :                     {
    4745               0 :                         samePalette = FALSE;
    4746                 :                     }
    4747                 :                 }
    4748                 :             }
    4749                 :             else
    4750                 :             {
    4751               0 :                 samePalette = FALSE;
    4752                 :             }
    4753               3 :             if (samePalette == FALSE)
    4754                 :             {
    4755               0 :                 if (pTranslationTable == NULL)
    4756               0 :                     pTranslationTable = (unsigned char*)CPLMalloc(256);
    4757                 : 
    4758                 :                 /* Trying to remap the product palette on the subdataset palette */
    4759               0 :                 for(i=0;i<nEntries;i++)
    4760                 :                 {
    4761               0 :                     if (bHasNoDataValueSrc && bHasNoDataValueRef && noDataValueSrc == i)
    4762               0 :                         continue;
    4763               0 :                     const GDALColorEntry* entry = srcColorTable->GetColorEntry(i);
    4764               0 :                     for(j=0;j<nRefEntries;j++)
    4765                 :                     {
    4766               0 :                         if (bHasNoDataValueRef && noDataValueRef == j)
    4767               0 :                             continue;
    4768               0 :                         const GDALColorEntry* entryRef = destColorTable->GetColorEntry(j);
    4769               0 :                         if (entry->c1 == entryRef->c1 &&
    4770                 :                             entry->c2 == entryRef->c2 &&
    4771                 :                             entry->c3 == entryRef->c3)
    4772                 :                         {
    4773               0 :                             pTranslationTable[i] = j;
    4774               0 :                             break;
    4775                 :                         }
    4776                 :                     }
    4777               0 :                     if (j == nEntries)
    4778                 :                     {
    4779                 :                         /* No exact match. Looking for closest color now... */
    4780               0 :                         int best_j = 0;
    4781               0 :                         int best_distance = 0;
    4782               0 :                         if (pApproximateMatching)
    4783               0 :                             *pApproximateMatching = TRUE;
    4784               0 :                         for(j=0;j<nRefEntries;j++)
    4785                 :                         {
    4786               0 :                             const GDALColorEntry* entryRef = destColorTable->GetColorEntry(j);
    4787                 :                             int distance = (entry->c1 - entryRef->c1) * (entry->c1 - entryRef->c1) +
    4788                 :                                            (entry->c2 - entryRef->c2) * (entry->c2 - entryRef->c2) +
    4789               0 :                                            (entry->c3 - entryRef->c3) * (entry->c3 - entryRef->c3);
    4790               0 :                             if (j == 0 || distance < best_distance)
    4791                 :                             {
    4792               0 :                                 best_j = j;
    4793               0 :                                 best_distance = distance;
    4794                 :                             }
    4795                 :                         }
    4796               0 :                         pTranslationTable[i] = best_j;
    4797                 :                     }
    4798                 :                 }
    4799               0 :                 if (bHasNoDataValueRef && bHasNoDataValueSrc)
    4800               0 :                     pTranslationTable[noDataValueSrc] = noDataValueRef;
    4801                 : 
    4802               0 :                 return pTranslationTable;
    4803                 :             }
    4804                 :         }
    4805                 :     }
    4806               3 :     return NULL;
    4807                 : }

Generated by: LCOV version 1.7