LCOV - code coverage report
Current view: directory - gcore - gdalrasterband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1345 849 63.1 %
Date: 2012-12-26 Functions: 105 84 80.0 %

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

Generated by: LCOV version 1.7