LCOV - code coverage report
Current view: directory - gcore - rasterio.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 763 633 83.0 %
Date: 2012-12-26 Functions: 228 169 74.1 %

       1                 : /******************************************************************************
       2                 :  * $Id: rasterio.cpp 25225 2012-11-11 19:29:06Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL Core
       5                 :  * Purpose:  Contains default implementation of GDALRasterBand::IRasterIO()
       6                 :  *           and supporting functions of broader utility.
       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                 : 
      33                 : // Define a list of "C++" compilers that have broken template support or
      34                 : // broken scoping so we can fall back on the legacy implementation of
      35                 : // GDALCopyWords
      36                 : #define NOT_BROKEN_COMPILER \
      37                 :   (!(defined(_MSC_VER) && _MSC_VER <= 1200) && !defined(__BORLANDC__) && \
      38                 :   !defined(__SUNPRO_CC))
      39                 : 
      40                 : #if NOT_BROKEN_COMPILER
      41                 : #include <stdexcept>
      42                 : #include <limits>
      43                 : 
      44                 : // For now, work around MSVC++ 6.0's broken template support. If this value
      45                 : // is not defined, the old GDALCopyWords implementation is used.
      46                 : #define USE_NEW_COPYWORDS 1
      47                 : #endif
      48                 : 
      49                 : 
      50                 : CPL_CVSID("$Id: rasterio.cpp 25225 2012-11-11 19:29:06Z rouault $");
      51                 : 
      52                 : /************************************************************************/
      53                 : /*                             IRasterIO()                              */
      54                 : /*                                                                      */
      55                 : /*      Default internal implementation of RasterIO() ... utilizes      */
      56                 : /*      the Block access methods to satisfy the request.  This would    */
      57                 : /*      normally only be overridden by formats with overviews.          */
      58                 : /************************************************************************/
      59                 : 
      60         1035108 : CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
      61                 :                                   int nXOff, int nYOff, int nXSize, int nYSize,
      62                 :                                   void * pData, int nBufXSize, int nBufYSize,
      63                 :                                   GDALDataType eBufType,
      64                 :                                   int nPixelSpace, int nLineSpace )
      65                 : 
      66                 : {
      67         1035108 :     int         nBandDataSize = GDALGetDataTypeSize( eDataType ) / 8;
      68         1035108 :     int         nBufDataSize = GDALGetDataTypeSize( eBufType ) / 8;
      69         1035108 :     GByte       *pabySrcBlock = NULL;
      70         1035108 :     GDALRasterBlock *poBlock = NULL;
      71         1035108 :     int         nLBlockX=-1, nLBlockY=-1, iBufYOff, iBufXOff, iSrcY;
      72                 : 
      73         1035108 :     if( eRWFlag == GF_Write && eFlushBlockErr != CE_None )
      74                 :     {
      75                 :         CPLError(eFlushBlockErr, CPLE_AppDefined,
      76               0 :                  "An error occured while writing a dirty block");
      77               0 :         CPLErr eErr = eFlushBlockErr;
      78               0 :         eFlushBlockErr = CE_None;
      79               0 :         return eErr;
      80                 :     }
      81                 : 
      82                 : /* ==================================================================== */
      83                 : /*      A common case is the data requested with the destination        */
      84                 : /*      is packed, and the block width is the raster width.             */
      85                 : /* ==================================================================== */
      86         1035108 :     if( nPixelSpace == nBufDataSize
      87                 :         && nLineSpace == nPixelSpace * nXSize
      88                 :         && nBlockXSize == GetXSize()
      89                 :         && nBufXSize == nXSize 
      90                 :         && nBufYSize == nYSize )
      91                 :     {
      92                 : //        printf( "IRasterIO(%d,%d,%d,%d) rw=%d case 1\n", 
      93                 : //                nXOff, nYOff, nXSize, nYSize, 
      94                 : //                (int) eRWFlag );
      95                 : 
      96         1281589 :         for( iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff++ )
      97                 :         {
      98                 :             int         nSrcByteOffset;
      99                 :             
     100          857408 :             iSrcY = iBufYOff + nYOff;
     101                 :             
     102          857408 :             if( iSrcY < nLBlockY * nBlockYSize
     103                 :                 || iSrcY >= (nLBlockY+1) * nBlockYSize )
     104                 :             {
     105          533517 :                 nLBlockY = iSrcY / nBlockYSize;
     106                 :                 int bJustInitialize = 
     107                 :                     eRWFlag == GF_Write
     108                 :                     && nXOff == 0 && nXSize == nBlockXSize
     109                 :                     && nYOff <= nLBlockY * nBlockYSize
     110          533517 :                     && nYOff + nYSize >= (nLBlockY+1) * nBlockYSize;
     111                 : 
     112          533517 :                 if( poBlock )
     113          109330 :                     poBlock->DropLock();
     114                 : 
     115          533517 :                 poBlock = GetLockedBlockRef( 0, nLBlockY, bJustInitialize );
     116          533517 :                 if( poBlock == NULL )
     117                 :                 {
     118                 :                     CPLError( CE_Failure, CPLE_AppDefined,
     119                 :             "GetBlockRef failed at X block offset %d, "
     120               6 :                         "Y block offset %d", 0, nLBlockY );
     121               6 :             return( CE_Failure );
     122                 :                 }
     123                 : 
     124          533511 :                 if( eRWFlag == GF_Write )
     125           58203 :                     poBlock->MarkDirty();
     126                 :                 
     127          533511 :                 pabySrcBlock = (GByte *) poBlock->GetDataRef();
     128          533511 :                 if( pabySrcBlock == NULL )
     129                 :                 {
     130               0 :                     poBlock->DropLock();
     131               0 :                     return CE_Failure;
     132                 :                 }
     133                 :             }
     134                 : 
     135                 :             nSrcByteOffset = ((iSrcY-nLBlockY*nBlockYSize)*nBlockXSize + nXOff)
     136          857402 :                 * nBandDataSize;
     137                 :             
     138          857402 :             if( eDataType == eBufType )
     139                 :             {
     140          510665 :                 if( eRWFlag == GF_Read )
     141                 :                     memcpy( ((GByte *) pData) + (size_t)iBufYOff * nLineSpace,
     142                 :                             pabySrcBlock + nSrcByteOffset, 
     143          361808 :                             nLineSpace );
     144                 :                 else
     145                 :                     memcpy( pabySrcBlock + nSrcByteOffset, 
     146                 :                             ((GByte *) pData) + (size_t)iBufYOff * nLineSpace,
     147          148857 :                             nLineSpace );
     148                 :             }
     149                 :             else
     150                 :             {
     151                 :                 /* type to type conversion */
     152                 :                 
     153          346737 :                 if( eRWFlag == GF_Read )
     154                 :                     GDALCopyWords( pabySrcBlock + nSrcByteOffset,
     155                 :                                    eDataType, nBandDataSize,
     156                 :                                    ((GByte *) pData) + (size_t)iBufYOff * nLineSpace,
     157          342911 :                                    eBufType, nPixelSpace, nBufXSize );
     158                 :                 else
     159                 :                     GDALCopyWords( ((GByte *) pData) + (size_t)iBufYOff * nLineSpace,
     160                 :                                    eBufType, nPixelSpace,
     161                 :                                    pabySrcBlock + nSrcByteOffset,
     162            3826 :                                    eDataType, nBandDataSize, nBufXSize );
     163                 :             }
     164                 :         }
     165                 : 
     166          424181 :         if( poBlock )
     167          424181 :             poBlock->DropLock();
     168                 : 
     169          424181 :         return CE_None;
     170                 :     }
     171                 :     
     172                 : /* ==================================================================== */
     173                 : /*      Do we have overviews that would be appropriate to satisfy       */
     174                 : /*      this request?                                                   */
     175                 : /* ==================================================================== */
     176          910279 :     if( (nBufXSize < nXSize || nBufYSize < nYSize)
     177          299358 :         && GetOverviewCount() > 0 && eRWFlag == GF_Read )
     178                 :     {
     179                 :         int         nOverview;
     180                 : 
     181                 :         nOverview =
     182                 :             GDALBandGetBestOverviewLevel(this, nXOff, nYOff, nXSize, nYSize,
     183              13 :                                         nBufXSize, nBufYSize);
     184              13 :         if (nOverview >= 0)
     185                 :         {
     186               9 :             GDALRasterBand* poOverviewBand = GetOverview(nOverview);
     187               9 :             if (poOverviewBand == NULL)
     188               0 :                 return CE_Failure;
     189                 : 
     190                 :             return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
     191                 :                                             pData, nBufXSize, nBufYSize, eBufType,
     192               9 :                                             nPixelSpace, nLineSpace );
     193                 :         }
     194                 :     }
     195                 : 
     196                 : /* ==================================================================== */
     197                 : /*      The second case when we don't need subsample data but likely    */
     198                 : /*      need data type conversion.                                      */
     199                 : /* ==================================================================== */
     200                 :     int         iSrcX;
     201                 : 
     202          610912 :     if ( /* nPixelSpace == nBufDataSize
     203                 :             && */ nXSize == nBufXSize
     204                 :          && nYSize == nBufYSize )    
     205                 :     {
     206                 : //        printf( "IRasterIO(%d,%d,%d,%d) rw=%d case 2\n", 
     207                 : //                nXOff, nYOff, nXSize, nYSize, 
     208                 : //                (int) eRWFlag );
     209                 : 
     210                 : /* -------------------------------------------------------------------- */
     211                 : /*      Loop over buffer computing source locations.                    */
     212                 : /* -------------------------------------------------------------------- */
     213                 :         int     nLBlockXStart, nXSpanEnd;
     214                 : 
     215                 :         // Calculate starting values out of loop
     216          276063 :         nLBlockXStart = nXOff / nBlockXSize;
     217          276063 :         nXSpanEnd = nBufXSize + nXOff;
     218                 : 
     219          276063 :         int nYInc = 0;
     220          568129 :         for( iBufYOff = 0, iSrcY = nYOff; iBufYOff < nBufYSize; iBufYOff+=nYInc, iSrcY+=nYInc )
     221                 :         {
     222                 :             size_t  iBufOffset, iSrcOffset;
     223                 :             int     nXSpan;
     224                 : 
     225          292072 :             iBufOffset = (size_t)iBufYOff * nLineSpace;
     226          292072 :             nLBlockY = iSrcY / nBlockYSize;
     227          292072 :             nLBlockX = nLBlockXStart;
     228          292072 :             iSrcX = nXOff;
     229         2620827 :             while( iSrcX < nXSpanEnd )
     230                 :             {
     231                 :                 int nXSpanSize;
     232                 : 
     233         2036689 :                 nXSpan = (nLBlockX + 1) * nBlockXSize;
     234         2036689 :                 nXSpan = ( ( nXSpan < nXSpanEnd )?nXSpan:nXSpanEnd ) - iSrcX;
     235         2036689 :                 nXSpanSize = nXSpan * nPixelSpace;
     236                 : 
     237                 :                 int bJustInitialize = 
     238                 :                     eRWFlag == GF_Write
     239                 :                     && nYOff <= nLBlockY * nBlockYSize
     240                 :                     && nYOff + nYSize >= (nLBlockY+1) * nBlockYSize
     241                 :                     && nXOff <= nLBlockX * nBlockXSize
     242         2036689 :                     && nXOff + nXSize >= (nLBlockX+1) * nBlockXSize;
     243                 : 
     244                 : //                printf( "bJustInitialize = %d (%d,%d,%d,%d)\n", 
     245                 : //                        bJustInitialize,
     246                 : //                        nYOff, nYSize, 
     247                 : //                        nLBlockY, nBlockYSize );
     248                 : //                bJustInitialize = FALSE;
     249                 :                 
     250                 : 
     251                 : /* -------------------------------------------------------------------- */
     252                 : /*      Ensure we have the appropriate block loaded.                    */
     253                 : /* -------------------------------------------------------------------- */
     254         2036689 :                 poBlock = GetLockedBlockRef( nLBlockX, nLBlockY, bJustInitialize );
     255         2036689 :                 if( !poBlock )
     256                 :                 {
     257                 :                     CPLError( CE_Failure, CPLE_AppDefined,
     258                 :             "GetBlockRef failed at X block offset %d, "
     259               6 :                         "Y block offset %d", nLBlockX, nLBlockY );
     260               6 :                     return( CE_Failure );
     261                 :                 }
     262                 : 
     263         2036683 :                 if( eRWFlag == GF_Write )
     264          210775 :                     poBlock->MarkDirty();
     265                 :                 
     266         2036683 :                 pabySrcBlock = (GByte *) poBlock->GetDataRef();
     267         2036683 :                 if( pabySrcBlock == NULL )
     268                 :                 {
     269               0 :                     poBlock->DropLock();
     270               0 :                     return CE_Failure;
     271                 :                 }
     272                 : 
     273                 : /* -------------------------------------------------------------------- */
     274                 : /*      Copy over this chunk of data.                                   */
     275                 : /* -------------------------------------------------------------------- */
     276                 :                 iSrcOffset = ((size_t)iSrcX - (size_t)nLBlockX*nBlockXSize
     277         2036683 :                     + ((size_t)(iSrcY) - (size_t)nLBlockY*nBlockYSize) * nBlockXSize)*nBandDataSize;
     278                 :                 /* Fill up as many rows as possible for the loaded block */
     279         2036683 :                 int kmax = MIN(nBlockYSize - (iSrcY % nBlockYSize), nBufYSize - iBufYOff);
     280         5035436 :                 for(int k=0; k<kmax;k++)
     281                 :                 {
     282         4124411 :                     if( eDataType == eBufType 
     283                 :                         && nPixelSpace == nBufDataSize )
     284                 :                     {
     285         1125658 :                         if( eRWFlag == GF_Read )
     286                 :                             memcpy( ((GByte *) pData) + iBufOffset + k * nLineSpace,
     287          552109 :                                     pabySrcBlock + iSrcOffset, nXSpanSize );
     288                 :                         else
     289                 :                             memcpy( pabySrcBlock + iSrcOffset, 
     290          573549 :                                     ((GByte *) pData) + iBufOffset + k * nLineSpace, nXSpanSize );
     291                 :                     }
     292                 :                     else
     293                 :                     {
     294                 :                         /* type to type conversion */
     295                 :                         
     296         1873095 :                         if( eRWFlag == GF_Read )
     297                 :                             GDALCopyWords( pabySrcBlock + iSrcOffset,
     298                 :                                         eDataType, nBandDataSize,
     299                 :                                         ((GByte *) pData) + iBufOffset + k * nLineSpace,
     300         1861164 :                                         eBufType, nPixelSpace, nXSpan );
     301                 :                         else
     302                 :                             GDALCopyWords( ((GByte *) pData) + iBufOffset + k * nLineSpace,
     303                 :                                         eBufType, nPixelSpace,
     304                 :                                         pabySrcBlock + iSrcOffset,
     305           11931 :                                         eDataType, nBandDataSize, nXSpan );
     306                 :                     }
     307                 :                     
     308         2998753 :                     iSrcOffset += nBlockXSize * nBandDataSize;
     309                 :                 }
     310                 : 
     311         2036683 :                 iBufOffset += nXSpanSize;
     312         2036683 :                 nLBlockX++;
     313         2036683 :                 iSrcX+=nXSpan;
     314                 : 
     315         2036683 :                 poBlock->DropLock();
     316         2036683 :                 poBlock = NULL;
     317                 :             }
     318                 : 
     319                 :             /* Compute the increment to go on a block boundary */
     320          292066 :             nYInc = nBlockYSize - (iSrcY % nBlockYSize);
     321                 :         }
     322                 : 
     323          276057 :         return CE_None;
     324                 :     }
     325                 : 
     326                 : /* ==================================================================== */
     327                 : /*      Loop reading required source blocks to satisfy output           */
     328                 : /*      request.  This is the most general implementation.              */
     329                 : /* ==================================================================== */
     330                 : 
     331                 : /* -------------------------------------------------------------------- */
     332                 : /*      Compute stepping increment.                                     */
     333                 : /* -------------------------------------------------------------------- */
     334                 :     double dfSrcXInc, dfSrcYInc;
     335          334849 :     dfSrcXInc = nXSize / (double) nBufXSize;
     336          334849 :     dfSrcYInc = nYSize / (double) nBufYSize;
     337                 : 
     338                 : 
     339                 : //    printf( "IRasterIO(%d,%d,%d,%d) rw=%d case 3\n", 
     340                 : //            nXOff, nYOff, nXSize, nYSize, 
     341                 : //            (int) eRWFlag );
     342          334849 :     if (eRWFlag == GF_Write)
     343                 :     {
     344                 : /* -------------------------------------------------------------------- */
     345                 : /*    Write case                                                        */
     346                 : /*    Loop over raster window computing source locations in the buffer. */
     347                 : /* -------------------------------------------------------------------- */
     348                 :         int iDstX, iDstY;
     349          165534 :         GByte* pabyDstBlock = NULL;
     350                 : 
     351         1251262 :         for( iDstY = nYOff; iDstY < nYOff + nYSize; iDstY ++)
     352                 :         {
     353                 :             size_t   iBufOffset, iDstOffset;
     354         1085728 :             iBufYOff = (int)((iDstY - nYOff) / dfSrcYInc);
     355                 : 
     356         8672666 :             for( iDstX = nXOff; iDstX < nXOff + nXSize; iDstX ++)
     357                 :             {
     358         7586938 :                 iBufXOff = (int)((iDstX - nXOff) / dfSrcXInc);
     359         7586938 :                 iBufOffset = (size_t)iBufYOff * nLineSpace + iBufXOff * nPixelSpace;
     360                 : 
     361                 :     /* -------------------------------------------------------------------- */
     362                 :     /*      Ensure we have the appropriate block loaded.                    */
     363                 :     /* -------------------------------------------------------------------- */
     364         7586938 :                 if( iDstX < nLBlockX * nBlockXSize
     365                 :                     || iDstX >= (nLBlockX+1) * nBlockXSize
     366                 :                     || iDstY < nLBlockY * nBlockYSize
     367                 :                     || iDstY >= (nLBlockY+1) * nBlockYSize )
     368                 :                 {
     369          734376 :                     nLBlockX = iDstX / nBlockXSize;
     370          734376 :                     nLBlockY = iDstY / nBlockYSize;
     371                 : 
     372                 :                     int bJustInitialize = 
     373                 :                            nYOff <= nLBlockY * nBlockYSize
     374                 :                         && nYOff + nYSize >= (nLBlockY+1) * nBlockYSize
     375                 :                         && nXOff <= nLBlockX * nBlockXSize
     376          734376 :                         && nXOff + nXSize >= (nLBlockX+1) * nBlockXSize;
     377                 : 
     378          734376 :                     if( poBlock != NULL )
     379          568842 :                         poBlock->DropLock();
     380                 : 
     381                 :                     poBlock = GetLockedBlockRef( nLBlockX, nLBlockY, 
     382          734376 :                                                 bJustInitialize );
     383          734376 :                     if( poBlock == NULL )
     384                 :                     {
     385               0 :                         return( CE_Failure );
     386                 :                     }
     387                 : 
     388          734376 :                     poBlock->MarkDirty();
     389                 : 
     390          734376 :                     pabyDstBlock = (GByte *) poBlock->GetDataRef();
     391          734376 :                     if( pabyDstBlock == NULL )
     392                 :                     {
     393               0 :                         poBlock->DropLock();
     394               0 :                         return CE_Failure;
     395                 :                     }
     396                 :                 }
     397                 : 
     398                 :     /* -------------------------------------------------------------------- */
     399                 :     /*      Copy over this pixel of data.                                   */
     400                 :     /* -------------------------------------------------------------------- */
     401                 :                 iDstOffset = ((size_t)iDstX - (size_t)nLBlockX*nBlockXSize
     402         7586938 :                     + ((size_t)iDstY - (size_t)nLBlockY*nBlockYSize) * nBlockXSize)*nBandDataSize;
     403                 : 
     404         7586938 :                 if( eDataType == eBufType )
     405                 :                 {
     406                 :                     memcpy( pabyDstBlock + iDstOffset, 
     407         7586338 :                             ((GByte *) pData) + iBufOffset, nBandDataSize );
     408                 :                 }
     409                 :                 else
     410                 :                 {
     411                 :                     /* type to type conversion ... ouch, this is expensive way
     412                 :                     of handling single words */
     413                 : 
     414                 :                     GDALCopyWords( ((GByte *) pData) + iBufOffset, eBufType, 0,
     415                 :                                 pabyDstBlock + iDstOffset, eDataType, 0,
     416             600 :                                 1 );
     417                 :                 }
     418                 :             }
     419                 :         }
     420                 :     }
     421                 :     else
     422                 :     {
     423                 :         double      dfSrcX, dfSrcY;
     424          169315 :         int         nLimitBlockY = 0;
     425          169315 :         int         bByteCopy = ( eDataType == eBufType && nBandDataSize == 1); 
     426          169315 :         int nStartBlockX = -nBlockXSize;
     427                 : 
     428                 : /* -------------------------------------------------------------------- */
     429                 : /*      Read case                                                       */
     430                 : /*      Loop over buffer computing source locations.                    */
     431                 : /* -------------------------------------------------------------------- */
     432          603772 :         for( iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff++ )
     433                 :         {
     434                 :             size_t   iBufOffset, iSrcOffset;
     435                 : 
     436          434457 :             dfSrcY = (iBufYOff+0.5) * dfSrcYInc + nYOff;
     437          434457 :             dfSrcX = 0.5 * dfSrcXInc + nXOff;
     438          434457 :             iSrcY = (int) dfSrcY;
     439                 : 
     440          434457 :             iBufOffset = (size_t)iBufYOff * nLineSpace;
     441                 : 
     442          434457 :             if( iSrcY >= nLimitBlockY )
     443                 :             {
     444          188711 :                 nLBlockY = iSrcY / nBlockYSize;
     445          188711 :                 nLimitBlockY = (nLBlockY + 1) * nBlockYSize;
     446          188711 :                 nStartBlockX = -nBlockXSize; /* make sure a new block is loaded */
     447                 :             }
     448          245746 :             else if( (int)dfSrcX < nStartBlockX )
     449           32875 :                 nStartBlockX = -nBlockXSize; /* make sure a new block is loaded */
     450                 : 
     451          434457 :             size_t iSrcOffsetCst = (iSrcY - nLBlockY*nBlockYSize) * (size_t)nBlockXSize;
     452                 : 
     453        19006914 :             for( iBufXOff = 0; iBufXOff < nBufXSize; iBufXOff++, dfSrcX += dfSrcXInc )
     454                 :             {
     455        18572457 :                 iSrcX = (int) dfSrcX;
     456        18572457 :                 int nDiffX = iSrcX - nStartBlockX;
     457                 : 
     458                 :     /* -------------------------------------------------------------------- */
     459                 :     /*      Ensure we have the appropriate block loaded.                    */
     460                 :     /* -------------------------------------------------------------------- */
     461        18572457 :                 if( nDiffX >= nBlockXSize )
     462                 :                 {
     463          565526 :                     nLBlockX = iSrcX / nBlockXSize;
     464          565526 :                     nStartBlockX = nLBlockX * nBlockXSize;
     465          565526 :                     nDiffX = iSrcX - nStartBlockX;
     466                 : 
     467          565526 :                     if( poBlock != NULL )
     468          396211 :                         poBlock->DropLock();
     469                 : 
     470                 :                     poBlock = GetLockedBlockRef( nLBlockX, nLBlockY, 
     471          565526 :                                                  FALSE );
     472          565526 :                     if( poBlock == NULL )
     473                 :                     {
     474               0 :                         return( CE_Failure );
     475                 :                     }
     476                 : 
     477          565526 :                     pabySrcBlock = (GByte *) poBlock->GetDataRef();
     478          565526 :                     if( pabySrcBlock == NULL )
     479                 :                     {
     480               0 :                         poBlock->DropLock();
     481               0 :                         return CE_Failure;
     482                 :                     }
     483                 :                 }
     484                 : 
     485                 :     /* -------------------------------------------------------------------- */
     486                 :     /*      Copy over this pixel of data.                                   */
     487                 :     /* -------------------------------------------------------------------- */
     488        18572457 :                 iSrcOffset = ((size_t)nDiffX + iSrcOffsetCst)*nBandDataSize;
     489                 : 
     490        18572457 :                 if( bByteCopy )
     491                 :                 {
     492        15766555 :                     ((GByte *) pData)[iBufOffset] = pabySrcBlock[iSrcOffset];
     493                 :                 }
     494         2805902 :                 else if( eDataType == eBufType )
     495                 :                 {
     496                 :                     memcpy( ((GByte *) pData) + iBufOffset,
     497         2164202 :                             pabySrcBlock + iSrcOffset, nBandDataSize );
     498                 :                 }
     499                 :                 else
     500                 :                 {
     501                 :                     /* type to type conversion ... ouch, this is expensive way
     502                 :                     of handling single words */
     503                 :                     GDALCopyWords( pabySrcBlock + iSrcOffset, eDataType, 0,
     504                 :                                 ((GByte *) pData) + iBufOffset, eBufType, 0,
     505          641700 :                                 1 );
     506                 :                 }
     507                 : 
     508        18572457 :                 iBufOffset += nPixelSpace;
     509                 :             }
     510                 :         }
     511                 :     }
     512                 : 
     513          334849 :     if( poBlock != NULL )
     514          334849 :         poBlock->DropLock();
     515                 : 
     516          334849 :     return( CE_None );
     517                 : }
     518                 : 
     519                 : /************************************************************************/
     520                 : /*                           GDALSwapWords()                            */
     521                 : /************************************************************************/
     522                 : 
     523                 : /**
     524                 :  * Byte swap words in-place.
     525                 :  *
     526                 :  * This function will byte swap a set of 2, 4 or 8 byte words "in place" in
     527                 :  * a memory array.  No assumption is made that the words being swapped are
     528                 :  * word aligned in memory.  Use the CPL_LSB and CPL_MSB macros from cpl_port.h
     529                 :  * to determine if the current platform is big endian or little endian.  Use
     530                 :  * The macros like CPL_SWAP32() to byte swap single values without the overhead
     531                 :  * of a function call. 
     532                 :  * 
     533                 :  * @param pData pointer to start of data buffer.
     534                 :  * @param nWordSize size of words being swapped in bytes. Normally 2, 4 or 8.
     535                 :  * @param nWordCount the number of words to be swapped in this call. 
     536                 :  * @param nWordSkip the byte offset from the start of one word to the start of
     537                 :  * the next. For packed buffers this is the same as nWordSize. 
     538                 :  */
     539                 : 
     540            9912 : void CPL_STDCALL GDALSwapWords( void *pData, int nWordSize, int nWordCount,
     541                 :                                 int nWordSkip )
     542                 : 
     543                 : {
     544            9912 :     if (nWordCount > 0)
     545            9912 :         VALIDATE_POINTER0( pData , "GDALSwapWords" );
     546                 : 
     547                 :     int         i;
     548            9912 :     GByte       *pabyData = (GByte *) pData;
     549                 : 
     550            9912 :     switch( nWordSize )
     551                 :     {
     552                 :       case 1:
     553               0 :         break;
     554                 : 
     555                 :       case 2:
     556            9690 :         CPLAssert( nWordSkip >= 2 || nWordCount == 1 );
     557        11368727 :         for( i = 0; i < nWordCount; i++ )
     558                 :         {
     559                 :             GByte       byTemp;
     560                 : 
     561        11359037 :             byTemp = pabyData[0];
     562        11359037 :             pabyData[0] = pabyData[1];
     563        11359037 :             pabyData[1] = byTemp;
     564                 : 
     565        11359037 :             pabyData += nWordSkip;
     566                 :         }
     567            9690 :         break;
     568                 :         
     569                 :       case 4:
     570             151 :         CPLAssert( nWordSkip >= 4 || nWordCount == 1 );
     571            3626 :         for( i = 0; i < nWordCount; i++ )
     572                 :         {
     573                 :             GByte       byTemp;
     574                 : 
     575            3475 :             byTemp = pabyData[0];
     576            3475 :             pabyData[0] = pabyData[3];
     577            3475 :             pabyData[3] = byTemp;
     578                 : 
     579            3475 :             byTemp = pabyData[1];
     580            3475 :             pabyData[1] = pabyData[2];
     581            3475 :             pabyData[2] = byTemp;
     582                 : 
     583            3475 :             pabyData += nWordSkip;
     584                 :         }
     585             151 :         break;
     586                 : 
     587                 :       case 8:
     588              71 :         CPLAssert( nWordSkip >= 8 || nWordCount == 1 );
     589            1103 :         for( i = 0; i < nWordCount; i++ )
     590                 :         {
     591                 :             GByte       byTemp;
     592                 : 
     593            1032 :             byTemp = pabyData[0];
     594            1032 :             pabyData[0] = pabyData[7];
     595            1032 :             pabyData[7] = byTemp;
     596                 : 
     597            1032 :             byTemp = pabyData[1];
     598            1032 :             pabyData[1] = pabyData[6];
     599            1032 :             pabyData[6] = byTemp;
     600                 : 
     601            1032 :             byTemp = pabyData[2];
     602            1032 :             pabyData[2] = pabyData[5];
     603            1032 :             pabyData[5] = byTemp;
     604                 : 
     605            1032 :             byTemp = pabyData[3];
     606            1032 :             pabyData[3] = pabyData[4];
     607            1032 :             pabyData[4] = byTemp;
     608                 : 
     609            1032 :             pabyData += nWordSkip;
     610                 :         }
     611              71 :         break;
     612                 : 
     613                 :       default:
     614               0 :         CPLAssert( FALSE );
     615                 :     }
     616                 : }
     617                 : 
     618                 : #ifdef USE_NEW_COPYWORDS
     619                 : // Place the new GDALCopyWords helpers in an anonymous namespace
     620                 : namespace {
     621                 : /************************************************************************/
     622                 : /*                          GetDataLimits()                             */
     623                 : /************************************************************************/
     624                 : /**
     625                 :  * Compute the limits of values that can be placed in Tout in terms of
     626                 :  * Tin. Usually used for output clamping, when the output data type's
     627                 :  * limits are stable relative to the input type (i.e. no roundoff error).
     628                 :  *
     629                 :  * @param tMaxValue the returned maximum value
     630                 :  * @param tMinValue the returned minimum value
     631                 :  */
     632                 : 
     633                 : template <class Tin, class Tout>
     634       426543234 : inline void GetDataLimits(Tin &tMaxValue, Tin &tMinValue)
     635                 : {
     636       426543234 :     tMaxValue = std::numeric_limits<Tin>::max();
     637       426356472 :     tMinValue = std::numeric_limits<Tin>::min();
     638                 : 
     639                 :     // Compute the actual minimum value of Tout in terms of Tin.
     640                 :     if (std::numeric_limits<Tout>::is_signed && std::numeric_limits<Tout>::is_integer)
     641                 :     {
     642                 :         // the minimum value is less than zero
     643                 :         if (std::numeric_limits<Tout>::digits < std::numeric_limits<Tin>::digits ||
     644                 :       !std::numeric_limits<Tin>::is_integer)
     645                 :         {
     646                 :             // Tout is smaller than Tin, so we need to clamp values in input
     647                 :             // to the range of Tout's min/max values
     648                 :             if (std::numeric_limits<Tin>::is_signed)
     649                 :             {
     650           38105 :                 tMinValue = static_cast<Tin>(std::numeric_limits<Tout>::min());
     651                 :             }
     652           56531 :             tMaxValue = static_cast<Tin>(std::numeric_limits<Tout>::max());
     653                 :         }
     654                 :     }
     655                 :     else if (std::numeric_limits<Tout>::is_integer)
     656                 :     {
     657                 :         // the output is unsigned, so we just need to determine the max
     658                 :         if (std::numeric_limits<Tout>::digits <= std::numeric_limits<Tin>::digits)
     659                 :         {
     660                 :             // Tout is smaller than Tin, so we need to clamp the input values
     661                 :             // to the range of Tout's max
     662        46010729 :             tMaxValue = static_cast<Tin>(std::numeric_limits<Tout>::max());
     663                 :         }
     664        46486248 :         tMinValue = 0;
     665                 :     }
     666                 : 
     667       426495804 : }
     668                 : 
     669                 : /************************************************************************/
     670                 : /*                            ClampValue()                                */
     671                 : /************************************************************************/
     672                 : /**
     673                 :  * Clamp values of type T to a specified range
     674                 :  *
     675                 :  * @param tValue the value
     676                 :  * @param tMax the max value
     677                 :  * @param tMin the min value
     678                 :  */
     679                 : template <class T>
     680       426217442 : inline T ClampValue(const T tValue, const T tMax, const T tMin)
     681                 : {
     682                 :     return tValue > tMax ? tMax :
     683       426217442 :            tValue < tMin ? tMin : tValue;
     684                 : }
     685                 : 
     686                 : /************************************************************************/
     687                 : /*                            CopyWord()                                */
     688                 : /************************************************************************/
     689                 : /**
     690                 :  * Copy a single word, optionally rounding if appropriate (i.e. going
     691                 :  * from the float to the integer case). Note that this is the function
     692                 :  * you should specialize if you're adding a new data type.
     693                 :  *
     694                 :  * @param tValueIn value of type Tin; the input value to be converted
     695                 :  * @param tValueOut value of type Tout; the output value
     696                 :  */
     697                 : 
     698                 : template <class Tin, class Tout>
     699       424897313 : inline void CopyWord(const Tin tValueIn, Tout &tValueOut)
     700                 : {
     701                 :     Tin tMaxVal, tMinVal;
     702       424897313 :     GetDataLimits<Tin, Tout>(tMaxVal, tMinVal);
     703       424881803 :     tValueOut = static_cast<Tout>(ClampValue(tValueIn, tMaxVal, tMinVal));
     704       424694233 : }
     705                 : 
     706                 : template <class Tin>
     707         8111653 : inline void CopyWord(const Tin tValueIn, float &fValueOut)
     708                 : {
     709         8111653 :     fValueOut = (float) tValueIn;
     710         8111653 : }
     711                 : 
     712                 : template <class Tin>
     713          166793 : inline void CopyWord(const Tin tValueIn, double &dfValueOut)
     714                 : {
     715          166793 :     dfValueOut = tValueIn;
     716          166793 : }
     717                 : 
     718             627 : inline void CopyWord(const double dfValueIn, double &dfValueOut)
     719                 : {
     720             627 :     dfValueOut = dfValueIn;
     721             627 : }
     722                 : 
     723          290819 : inline void CopyWord(const float fValueIn, float &fValueOut)
     724                 : {
     725          290819 :     fValueOut = fValueIn;
     726          290819 : }
     727                 : 
     728         1623291 : inline void CopyWord(const float fValueIn, double &dfValueOut)
     729                 : {
     730         1623291 :     dfValueOut = fValueIn;
     731         1623291 : }
     732                 : 
     733            3225 : inline void CopyWord(const double dfValueIn, float &fValueOut)
     734                 : {
     735            3225 :     fValueOut = static_cast<float>(dfValueIn);
     736            3225 : }
     737                 : 
     738                 : template <class Tout>
     739         1280911 : inline void CopyWord(const float fValueIn, Tout &tValueOut)
     740                 : {
     741                 :     float fMaxVal, fMinVal;
     742         1280911 :     GetDataLimits<float, Tout>(fMaxVal, fMinVal);
     743         1280911 :     tValueOut = static_cast<Tout>(
     744                 :         ClampValue(fValueIn + 0.5f, fMaxVal, fMinVal));
     745         1280911 : }
     746                 : 
     747                 : template <class Tout>
     748          189596 : inline void CopyWord(const double dfValueIn, Tout &tValueOut)
     749                 : {
     750                 :     double dfMaxVal, dfMinVal;
     751          189596 :     GetDataLimits<double, Tout>(dfMaxVal, dfMinVal);
     752          189595 :     tValueOut = static_cast<Tout>(
     753                 :         ClampValue(dfValueIn + 0.5, dfMaxVal, dfMinVal));
     754          189596 : }
     755                 : 
     756            1658 : inline void CopyWord(const double dfValueIn, int &nValueOut)
     757                 : {
     758                 :     double dfMaxVal, dfMinVal;
     759            1658 :     GetDataLimits<double, int>(dfMaxVal, dfMinVal);
     760                 :     double dfValue = dfValueIn >= 0.0 ? dfValueIn + 0.5 :
     761            1658 :         dfValueIn - 0.5;
     762                 :     nValueOut = static_cast<int>(
     763            1658 :         ClampValue(dfValue, dfMaxVal, dfMinVal));
     764            1658 : }
     765                 : 
     766           19753 : inline void CopyWord(const float fValueIn, short &nValueOut)
     767                 : {
     768                 :     float fMaxVal, fMinVal;
     769           19753 :     GetDataLimits<float, short>(fMaxVal, fMinVal);
     770                 :     float fValue = fValueIn >= 0.0f ? fValueIn + 0.5f :
     771           19753 :         fValueIn - 0.5f;
     772                 :     nValueOut = static_cast<short>(
     773           19753 :         ClampValue(fValue, fMaxVal, fMinVal));
     774           19753 : }
     775                 : 
     776           14803 : inline void CopyWord(const double dfValueIn, short &nValueOut)
     777                 : {
     778                 :     double dfMaxVal, dfMinVal;
     779           14803 :     GetDataLimits<double, short>(dfMaxVal, dfMinVal);
     780                 :     double dfValue = dfValueIn > 0.0 ? dfValueIn + 0.5 :
     781           14799 :         dfValueIn - 0.5;
     782                 :     nValueOut = static_cast<short>(
     783           14799 :         ClampValue(dfValue, dfMaxVal, dfMinVal));
     784           14798 : }
     785                 : 
     786                 : // Roundoff occurs for Float32 -> int32 for max/min. Overload CopyWord
     787                 : // specifically for this case.
     788          697656 : inline void CopyWord(const float fValueIn, int &nValueOut)
     789                 : {
     790          697656 :     if (fValueIn >= static_cast<float>(std::numeric_limits<int>::max()))
     791                 :     {
     792               0 :         nValueOut = std::numeric_limits<int>::max();
     793                 :     }
     794          697656 :     else if (fValueIn <= static_cast<float>(std::numeric_limits<int>::min()))
     795                 :     {
     796               0 :         nValueOut = std::numeric_limits<int>::min();
     797                 :     }
     798                 :     else
     799                 :     {
     800                 :         nValueOut = static_cast<int>(fValueIn > 0.0f ? 
     801          697656 :             fValueIn + 0.5f : fValueIn - 0.5f);
     802                 :     }
     803          697656 : }
     804                 : 
     805                 : // Roundoff occurs for Float32 -> uint32 for max. Overload CopyWord
     806                 : // specifically for this case.
     807             200 : inline void CopyWord(const float fValueIn, unsigned int &nValueOut)
     808                 : {
     809             200 :     if (fValueIn >= static_cast<float>(std::numeric_limits<unsigned int>::max()))
     810                 :     {
     811               0 :         nValueOut = std::numeric_limits<unsigned int>::max();
     812                 :     }
     813             200 :     else if (fValueIn <= static_cast<float>(std::numeric_limits<unsigned int>::min()))
     814                 :     {
     815               0 :         nValueOut = std::numeric_limits<unsigned int>::min();
     816                 :     }
     817                 :     else
     818                 :     {
     819             200 :         nValueOut = static_cast<unsigned int>(fValueIn + 0.5f);
     820                 :     }
     821             200 : }
     822                 : 
     823                 : /************************************************************************/
     824                 : /*                           GDALCopyWordsT()                           */
     825                 : /************************************************************************/
     826                 : /**
     827                 :  * Template function, used to copy data from pSrcData into buffer
     828                 :  * pDstData, with stride nSrcPixelOffset in the source data and
     829                 :  * stride nDstPixelOffset in the destination data. This template can
     830                 :  * deal with the case where the input data type is real or complex and
     831                 :  * the output is real.
     832                 :  *
     833                 :  * @param pSrcData the source data buffer
     834                 :  * @param nSrcPixelOffset the stride, in the buffer pSrcData for pixels
     835                 :  *                      of interest.
     836                 :  * @param pDstData the destination buffer.
     837                 :  * @param nDstPixelOffset the stride in the buffer pDstData for pixels of
     838                 :  *                      interest.
     839                 :  * @param nWordCount the total number of pixel words to copy
     840                 :  *
     841                 :  * @code
     842                 :  * // Assume an input buffer of type GUInt16 named pBufferIn 
     843                 :  * GByte *pBufferOut = new GByte[numBytesOut];
     844                 :  * GDALCopyWordsT<GUInt16, GByte>(pSrcData, 2, pDstData, 1, numBytesOut);
     845                 :  * @code
     846                 :  * @note
     847                 :  * This is a private function, and should not be exposed outside of rasterio.cpp.
     848                 :  * External users should call the GDALCopyWords driver function.
     849                 :  * @note
     850                 :  */
     851                 : 
     852                 : template <class Tin, class Tout>
     853         3828839 : static void GDALCopyWordsT(const Tin* const pSrcData, int nSrcPixelOffset,
     854                 :                            Tout* const pDstData, int nDstPixelOffset,
     855                 :                            int nWordCount)
     856                 : {
     857         3828839 :     std::ptrdiff_t nDstOffset = 0;
     858                 : 
     859         3828839 :     const char* const pSrcDataPtr = reinterpret_cast<const char*>(pSrcData);
     860         3828839 :     char* const pDstDataPtr = reinterpret_cast<char*>(pDstData);
     861       440914748 :     for (std::ptrdiff_t n = 0; n < nWordCount; n++)
     862                 :     {
     863       437096580 :         const Tin tValue = *reinterpret_cast<const Tin*>(pSrcDataPtr + (n * nSrcPixelOffset));
     864       437096580 :         Tout* const pOutPixel = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
     865                 : 
     866       437096580 :         CopyWord(tValue, *pOutPixel);
     867                 : 
     868       437085909 :         nDstOffset += nDstPixelOffset;
     869                 :     }
     870         3818168 : }
     871                 : 
     872                 : /************************************************************************/
     873                 : /*                   GDALCopyWordsComplexT()                            */
     874                 : /************************************************************************/
     875                 : /**
     876                 :  * Template function, used to copy data from pSrcData into buffer
     877                 :  * pDstData, with stride nSrcPixelOffset in the source data and
     878                 :  * stride nDstPixelOffset in the destination data. Deals with the 
     879                 :  * complex case, where input is complex and output is complex.
     880                 :  *
     881                 :  * @param pSrcData the source data buffer
     882                 :  * @param nSrcPixelOffset the stride, in the buffer pSrcData for pixels
     883                 :  *                      of interest.
     884                 :  * @param pDstData the destination buffer.
     885                 :  * @param nDstPixelOffset the stride in the buffer pDstData for pixels of
     886                 :  *                      interest.
     887                 :  * @param nWordCount the total number of pixel words to copy
     888                 :  *
     889                 :  */
     890                 : template <class Tin, class Tout>
     891            1028 : inline void GDALCopyWordsComplexT(const Tin* const pSrcData, int nSrcPixelOffset,
     892                 :                                   Tout* const pDstData, int nDstPixelOffset,
     893                 :                                   int nWordCount)
     894                 : {
     895            1028 :     std::ptrdiff_t nDstOffset = 0;
     896            1028 :     const char* const pSrcDataPtr = reinterpret_cast<const char*>(pSrcData);
     897            1028 :     char* const pDstDataPtr = reinterpret_cast<char*>(pDstData);
     898                 : 
     899                 :     // Determine the minimum and maximum value we can have based
     900                 :     // on the constraints of Tin and Tout.
     901                 :     Tin tMaxValue, tMinValue;
     902            1028 :     GetDataLimits<Tin, Tout>(tMaxValue, tMinValue);
     903                 : 
     904           14620 :     for (std::ptrdiff_t n = 0; n < nWordCount; n++)
     905                 :     {
     906           13592 :         const Tin* const pPixelIn = reinterpret_cast<const Tin*>(pSrcDataPtr + n * nSrcPixelOffset);
     907           13592 :         Tout* const pPixelOut = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
     908                 : 
     909           13592 :         CopyWord(pPixelIn[0], pPixelOut[0]);
     910           13592 :         CopyWord(pPixelIn[1], pPixelOut[1]);
     911                 : 
     912           13592 :         nDstOffset += nDstPixelOffset;
     913                 :     }
     914            1028 : }
     915                 : 
     916                 : /************************************************************************/
     917                 : /*                   GDALCopyWordsComplexOutT()                         */
     918                 : /************************************************************************/
     919                 : /**
     920                 :  * Template function, used to copy data from pSrcData into buffer
     921                 :  * pDstData, with stride nSrcPixelOffset in the source data and
     922                 :  * stride nDstPixelOffset in the destination data. Deals with the 
     923                 :  * case where the value is real coming in, but complex going out.
     924                 :  *
     925                 :  * @param pSrcData the source data buffer
     926                 :  * @param nSrcPixelOffset the stride, in the buffer pSrcData for pixels
     927                 :  *                      of interest, in bytes.
     928                 :  * @param pDstData the destination buffer.
     929                 :  * @param nDstPixelOffset the stride in the buffer pDstData for pixels of
     930                 :  *                      interest, in bytes.
     931                 :  * @param nWordCount the total number of pixel words to copy
     932                 :  *
     933                 :  */
     934                 : template <class Tin, class Tout>
     935             247 : inline void GDALCopyWordsComplexOutT(const Tin* const pSrcData, int nSrcPixelOffset,
     936                 :                                      Tout* const pDstData, int nDstPixelOffset,
     937                 :                                      int nWordCount)
     938                 : {
     939             247 :     std::ptrdiff_t nDstOffset = 0;
     940                 : 
     941             247 :     const Tout tOutZero = static_cast<Tout>(0);
     942                 : 
     943             247 :     const char* const pSrcDataPtr = reinterpret_cast<const char*>(pSrcData);
     944             247 :     char* const pDstDataPtr = reinterpret_cast<char*>(pDstData);
     945                 : 
     946            4254 :     for (std::ptrdiff_t n = 0; n < nWordCount; n++)
     947                 :     {
     948            4007 :         const Tin tValue = *reinterpret_cast<const Tin* const>(pSrcDataPtr + n * nSrcPixelOffset);
     949            4007 :         Tout* const pPixelOut = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
     950            4007 :         CopyWord(tValue, *pPixelOut);
     951                 : 
     952            4007 :         pPixelOut[1] = tOutZero;
     953                 : 
     954            4007 :         nDstOffset += nDstPixelOffset;
     955                 :     }
     956             247 : }
     957                 : 
     958                 : /************************************************************************/
     959                 : /*                           GDALCopyWordsFromT()                       */
     960                 : /************************************************************************/
     961                 : /**
     962                 :  * Template driver function. Given the input type T, call the appropriate
     963                 :  * GDALCopyWordsT function template for the desired output type. You should
     964                 :  * never call this function directly (call GDALCopyWords instead).
     965                 :  *
     966                 :  * @param pSrcData source data buffer
     967                 :  * @param nSrcPixelOffset pixel stride in input buffer, in pixel words
     968                 :  * @param bInComplex input is complex
     969                 :  * @param pDstData destination data buffer
     970                 :  * @param eDstType destination data type
     971                 :  * @param nDstPixelOffset pixel stride in output buffer, in pixel words
     972                 :  * @param nWordCount number of pixel words to be copied
     973                 :  */
     974                 : template <class T>
     975         3819448 : inline void GDALCopyWordsFromT(const T* const pSrcData, int nSrcPixelOffset, bool bInComplex,
     976                 :                                void *pDstData, GDALDataType eDstType, int nDstPixelOffset,
     977                 :                                int nWordCount)
     978                 : {
     979         3819448 :     switch (eDstType)
     980                 :     {
     981                 :     case GDT_Byte:
     982          325329 :         GDALCopyWordsT(pSrcData, nSrcPixelOffset,
     983                 :                        static_cast<unsigned char*>(pDstData), nDstPixelOffset,
     984                 :                        nWordCount);
     985          325324 :         break;
     986                 :     case GDT_UInt16:
     987            1507 :         GDALCopyWordsT(pSrcData, nSrcPixelOffset,
     988                 :                        static_cast<unsigned short*>(pDstData), nDstPixelOffset,
     989                 :                        nWordCount);
     990            1507 :         break;
     991                 :     case GDT_Int16:
     992            3360 :         GDALCopyWordsT(pSrcData, nSrcPixelOffset,
     993                 :                        static_cast<short*>(pDstData), nDstPixelOffset,
     994                 :                        nWordCount);
     995            3360 :         break;
     996                 :     case GDT_UInt32:
     997            2092 :         GDALCopyWordsT(pSrcData, nSrcPixelOffset,
     998                 :                        static_cast<unsigned int*>(pDstData), nDstPixelOffset,
     999                 :                        nWordCount);
    1000            2092 :         break;
    1001                 :     case GDT_Int32:
    1002         3101881 :         GDALCopyWordsT(pSrcData, nSrcPixelOffset,
    1003                 :                        static_cast<int*>(pDstData), nDstPixelOffset,
    1004                 :                        nWordCount);
    1005         3101881 :         break;
    1006                 :     case GDT_Float32:
    1007          339142 :         GDALCopyWordsT(pSrcData, nSrcPixelOffset,
    1008                 :                        static_cast<float*>(pDstData), nDstPixelOffset,
    1009                 :                        nWordCount);
    1010          339142 :         break;
    1011                 :     case GDT_Float64:
    1012           44862 :         GDALCopyWordsT(pSrcData, nSrcPixelOffset,
    1013                 :                        static_cast<double*>(pDstData), nDstPixelOffset,
    1014                 :                        nWordCount);
    1015           44862 :         break;
    1016                 :     case GDT_CInt16:
    1017              82 :         if (bInComplex)
    1018                 :         {
    1019              42 :             GDALCopyWordsComplexT(pSrcData, nSrcPixelOffset,
    1020                 :                                   static_cast<short *>(pDstData), nDstPixelOffset,
    1021                 :                                   nWordCount);
    1022                 :         }
    1023                 :         else // input is not complex, so we need to promote to a complex buffer
    1024                 :         {
    1025              40 :             GDALCopyWordsComplexOutT(pSrcData, nSrcPixelOffset,
    1026                 :                                      static_cast<short *>(pDstData), nDstPixelOffset,
    1027                 :                                      nWordCount);
    1028                 :         }
    1029              82 :         break;
    1030                 :     case GDT_CInt32:
    1031             352 :         if (bInComplex)
    1032                 :         {
    1033             312 :             GDALCopyWordsComplexT(pSrcData, nSrcPixelOffset,
    1034                 :                                   static_cast<int *>(pDstData), nDstPixelOffset,
    1035                 :                                   nWordCount);
    1036                 :         }
    1037                 :         else // input is not complex, so we need to promote to a complex buffer
    1038                 :         {
    1039              40 :             GDALCopyWordsComplexOutT(pSrcData, nSrcPixelOffset,
    1040                 :                                      static_cast<int *>(pDstData), nDstPixelOffset,
    1041                 :                                      nWordCount);
    1042                 :         }
    1043             352 :         break;
    1044                 :     case GDT_CFloat32:
    1045             218 :         if (bInComplex)
    1046                 :         {
    1047             178 :             GDALCopyWordsComplexT(pSrcData, nSrcPixelOffset,
    1048                 :                                   static_cast<float *>(pDstData), nDstPixelOffset,
    1049                 :                                   nWordCount);
    1050                 :         }
    1051                 :         else // input is not complex, so we need to promote to a complex buffer
    1052                 :         {
    1053              40 :             GDALCopyWordsComplexOutT(pSrcData, nSrcPixelOffset,
    1054                 :                                      static_cast<float *>(pDstData), nDstPixelOffset,
    1055                 :                                      nWordCount);
    1056                 :         }
    1057             218 :         break;
    1058                 :     case GDT_CFloat64:
    1059             623 :         if (bInComplex)
    1060                 :         {
    1061             496 :             GDALCopyWordsComplexT(pSrcData, nSrcPixelOffset,
    1062                 :                                   static_cast<double *>(pDstData), nDstPixelOffset,
    1063                 :                                   nWordCount);
    1064                 :         }
    1065                 :         else // input is not complex, so we need to promote to a complex buffer
    1066                 :         {
    1067             127 :             GDALCopyWordsComplexOutT(pSrcData, nSrcPixelOffset,
    1068                 :                                      static_cast<double *>(pDstData), nDstPixelOffset,
    1069                 :                                      nWordCount);
    1070                 :         }
    1071             623 :         break;
    1072                 :     case GDT_Unknown:
    1073                 :     default:
    1074               0 :         CPLAssert(FALSE);
    1075                 :     }
    1076         3819443 : }
    1077                 : 
    1078                 : } // end anonymous namespace
    1079                 : #endif
    1080                 : 
    1081                 : /************************************************************************/
    1082                 : /*                          GDALReplicateWord()                         */
    1083                 : /************************************************************************/
    1084                 : 
    1085            4005 : void GDALReplicateWord(void *pSrcData, GDALDataType eSrcType,
    1086                 :                        void *pDstData, GDALDataType eDstType, int nDstPixelOffset,
    1087                 :                        int nWordCount)
    1088                 : {
    1089                 : /* ----------------------------------------------------------------------- */
    1090                 : /* Special case when the source data is always the same value              */
    1091                 : /* (for VRTSourcedRasterBand::IRasterIO and VRTDerivedRasterBand::IRasterIO*/
    1092                 : /*  for example)                                                           */
    1093                 : /* ----------------------------------------------------------------------- */
    1094                 :     /* Let the general translation case do the necessary conversions */
    1095                 :     /* on the first destination element */
    1096                 :     GDALCopyWords(pSrcData, eSrcType, 0,
    1097                 :                   pDstData, eDstType, nDstPixelOffset,
    1098            4005 :                   1 );
    1099                 : 
    1100                 :     /* Now copy the first element to the nWordCount - 1 following destination */
    1101                 :     /* elements */
    1102            4005 :     nWordCount--;
    1103            4005 :     GByte *pabyDstWord = ((GByte *)pDstData) + nDstPixelOffset;
    1104                 : 
    1105            4005 :     switch (eDstType)
    1106                 :     {
    1107                 :         case GDT_Byte:
    1108                 :         {
    1109            1703 :             if (nDstPixelOffset == 1)
    1110                 :             {
    1111            1703 :                 if (nWordCount > 0)
    1112            1703 :                     memset(pabyDstWord, *(GByte*)pDstData, nWordCount);
    1113                 :             }
    1114                 :             else
    1115                 :             {
    1116               0 :                 GByte valSet = *(GByte*)pDstData;
    1117               0 :                 while(nWordCount--)
    1118                 :                 {
    1119               0 :                     *pabyDstWord = valSet;
    1120               0 :                     pabyDstWord += nDstPixelOffset;
    1121                 :                 }
    1122                 :             }
    1123            1703 :             break;
    1124                 :         }
    1125                 : 
    1126                 : #define CASE_DUPLICATE_SIMPLE(enum_type, c_type) \
    1127                 :         case enum_type:\
    1128                 :         { \
    1129                 :             c_type valSet = *(c_type*)pDstData; \
    1130                 :             while(nWordCount--) \
    1131                 :             { \
    1132                 :                 *(c_type*)pabyDstWord = valSet; \
    1133                 :                 pabyDstWord += nDstPixelOffset; \
    1134                 :             } \
    1135                 :             break; \
    1136                 :         }
    1137                 : 
    1138             246 :         CASE_DUPLICATE_SIMPLE(GDT_UInt16, GUInt16)
    1139              48 :         CASE_DUPLICATE_SIMPLE(GDT_Int16,  GInt16)
    1140             240 :         CASE_DUPLICATE_SIMPLE(GDT_UInt32, GUInt32)
    1141            1586 :         CASE_DUPLICATE_SIMPLE(GDT_Int32,  GInt32)
    1142             140 :         CASE_DUPLICATE_SIMPLE(GDT_Float32,float)
    1143              42 :         CASE_DUPLICATE_SIMPLE(GDT_Float64,double)
    1144                 : 
    1145                 : #define CASE_DUPLICATE_COMPLEX(enum_type, c_type) \
    1146                 :         case enum_type:\
    1147                 :         { \
    1148                 :             c_type valSet1 = ((c_type*)pDstData)[0]; \
    1149                 :             c_type valSet2 = ((c_type*)pDstData)[1]; \
    1150                 :             while(nWordCount--) \
    1151                 :             { \
    1152                 :                 ((c_type*)pabyDstWord)[0] = valSet1; \
    1153                 :                 ((c_type*)pabyDstWord)[1] = valSet2; \
    1154                 :                 pabyDstWord += nDstPixelOffset; \
    1155                 :             } \
    1156                 :             break; \
    1157                 :         }
    1158                 : 
    1159               0 :         CASE_DUPLICATE_COMPLEX(GDT_CInt16, GInt16)
    1160               0 :         CASE_DUPLICATE_COMPLEX(GDT_CInt32, GInt32)
    1161               0 :         CASE_DUPLICATE_COMPLEX(GDT_CFloat32, float)
    1162               0 :         CASE_DUPLICATE_COMPLEX(GDT_CFloat64, double)
    1163                 : 
    1164                 :         default:
    1165               0 :             CPLAssert( FALSE );
    1166                 :     }
    1167            4005 : }
    1168                 : 
    1169                 : /************************************************************************/
    1170                 : /*                           GDALCopyWords()                            */
    1171                 : /************************************************************************/
    1172                 : 
    1173                 : /**
    1174                 :  * Copy pixel words from buffer to buffer.
    1175                 :  *
    1176                 :  * This function is used to copy pixel word values from one memory buffer
    1177                 :  * to another, with support for conversion between data types, and differing
    1178                 :  * step factors.  The data type conversion is done using the normal GDAL 
    1179                 :  * rules.  Values assigned to a lower range integer type are clipped.  For
    1180                 :  * instance assigning GDT_Int16 values to a GDT_Byte buffer will cause values
    1181                 :  * less the 0 to be set to 0, and values larger than 255 to be set to 255. 
    1182                 :  * Assignment from floating point to integer uses default C type casting
    1183                 :  * semantics.   Assignment from non-complex to complex will result in the 
    1184                 :  * imaginary part being set to zero on output.  Assigment from complex to 
    1185                 :  * non-complex will result in the complex portion being lost and the real
    1186                 :  * component being preserved (<i>not magnitidue!</i>). 
    1187                 :  *
    1188                 :  * No assumptions are made about the source or destination words occuring
    1189                 :  * on word boundaries.  It is assumed that all values are in native machine
    1190                 :  * byte order. 
    1191                 :  *
    1192                 :  * @param pSrcData Pointer to source data to be converted.
    1193                 :  * @param eSrcType the source data type (see GDALDataType enum)
    1194                 :  * @param nSrcPixelOffset Source pixel offset, in bytes
    1195                 :  * @param pDstData Pointer to buffer where destination data should go
    1196                 :  * @param eDstType the destination data type (see GDALDataType enum)
    1197                 :  * @param nDstPixelOffset Destination pixel offset, in bytes
    1198                 :  * @param nWordCount number of words to be copied
    1199                 :  *
    1200                 :  * 
    1201                 :  * @note 
    1202                 :  * When adding a new data type to GDAL, you must do the following to
    1203                 :  * support it properly within the GDALCopyWords function:
    1204                 :  * 1. Add the data type to the switch on eSrcType in GDALCopyWords.
    1205                 :  *    This should invoke the appropriate GDALCopyWordsFromT wrapper.
    1206                 :  * 2. Add the data type to the switch on eDstType in GDALCopyWordsFromT.
    1207                 :  *    This should call the appropriate GDALCopyWordsT template.
    1208                 :  * 3. If appropriate, overload the appropriate CopyWord template in the
    1209                 :  *    above namespace. This will ensure that any conversion issues are
    1210                 :  *    handled (cases like the float -> int32 case, where the min/max)
    1211                 :  *    values are subject to roundoff error.
    1212                 :  */
    1213                 : 
    1214                 : void CPL_STDCALL
    1215         4154637 : GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
    1216                 :                void * pDstData, GDALDataType eDstType, int nDstPixelOffset,
    1217                 :                int nWordCount )
    1218                 : 
    1219                 : {
    1220                 :     // Deal with the case where we're replicating a single word into the
    1221                 :     // provided buffer
    1222         4154637 :     if (nSrcPixelOffset == 0 && nWordCount > 1)
    1223                 :     {
    1224            4005 :         GDALReplicateWord(pSrcData, eSrcType, pDstData, eDstType, nDstPixelOffset, nWordCount);
    1225            4005 :         return;
    1226                 :     }
    1227                 : 
    1228                 : #ifdef USE_NEW_COPYWORDS
    1229                 : 
    1230         4150632 :     int nSrcDataTypeSize = GDALGetDataTypeSize(eSrcType) / 8;
    1231                 :     // Let memcpy() handle the case where we're copying a packed buffer
    1232                 :     // of pixels.
    1233         4150643 :     if (eSrcType == eDstType && nSrcPixelOffset == nDstPixelOffset &&
    1234                 :         nSrcPixelOffset == nSrcDataTypeSize)
    1235                 :     {
    1236          331195 :         memcpy(pDstData, pSrcData, nWordCount * nSrcDataTypeSize);
    1237          331195 :         return;
    1238                 :     }
    1239                 : 
    1240                 :     // Handle the more general case -- deals with conversion of data types
    1241                 :     // directly.
    1242         3819448 :     switch (eSrcType)
    1243                 :     {
    1244                 :     case GDT_Byte:
    1245                 :         GDALCopyWordsFromT<unsigned char>(static_cast<unsigned char *>(pSrcData), nSrcPixelOffset, false,
    1246                 :                                  pDstData, eDstType, nDstPixelOffset,
    1247         1611943 :                                  nWordCount);
    1248         1611943 :         break;
    1249                 :     case GDT_UInt16:
    1250                 :         GDALCopyWordsFromT<unsigned short>(static_cast<unsigned short *>(pSrcData), nSrcPixelOffset, false,
    1251                 :                                            pDstData, eDstType, nDstPixelOffset,
    1252           17390 :                                            nWordCount);
    1253           17390 :         break;
    1254                 :     case GDT_Int16:
    1255                 :         GDALCopyWordsFromT<short>(static_cast<short *>(pSrcData), nSrcPixelOffset, false,
    1256                 :                                   pDstData, eDstType, nDstPixelOffset,
    1257         1263182 :                                   nWordCount);
    1258         1263182 :         break;
    1259                 :     case GDT_UInt32:
    1260                 :         GDALCopyWordsFromT<unsigned int>(static_cast<unsigned int *>(pSrcData), nSrcPixelOffset, false,
    1261                 :                                          pDstData, eDstType, nDstPixelOffset,
    1262            1471 :                                          nWordCount);
    1263            1471 :         break;
    1264                 :     case GDT_Int32:
    1265                 :         GDALCopyWordsFromT<int>(static_cast<int *>(pSrcData), nSrcPixelOffset, false,
    1266                 :                                 pDstData, eDstType, nDstPixelOffset,
    1267           12732 :                                 nWordCount);
    1268           12730 :         break;
    1269                 :     case GDT_Float32:
    1270                 :         GDALCopyWordsFromT<float>(static_cast<float *>(pSrcData), nSrcPixelOffset, false,
    1271                 :                                   pDstData, eDstType, nDstPixelOffset,
    1272          737915 :                                   nWordCount);
    1273          737915 :         break;
    1274                 :     case GDT_Float64:
    1275                 :         GDALCopyWordsFromT<double>(static_cast<double *>(pSrcData), nSrcPixelOffset, false,
    1276                 :                                    pDstData, eDstType, nDstPixelOffset,
    1277            5005 :                                    nWordCount);
    1278            5002 :         break;
    1279                 :     case GDT_CInt16:
    1280                 :         GDALCopyWordsFromT<short>(static_cast<short *>(pSrcData), nSrcPixelOffset, true,
    1281                 :                                  pDstData, eDstType, nDstPixelOffset,
    1282             549 :                                  nWordCount);
    1283             549 :         break;
    1284                 :     case GDT_CInt32:
    1285                 :         GDALCopyWordsFromT<int>(static_cast<int *>(pSrcData), nSrcPixelOffset, true,
    1286                 :                                  pDstData, eDstType, nDstPixelOffset,
    1287             283 :                                  nWordCount);
    1288             283 :         break;
    1289                 :     case GDT_CFloat32:
    1290                 :         GDALCopyWordsFromT<float>(static_cast<float *>(pSrcData), nSrcPixelOffset, true,
    1291                 :                                  pDstData, eDstType, nDstPixelOffset,
    1292             698 :                                  nWordCount);
    1293             698 :         break;
    1294                 :     case GDT_CFloat64:
    1295                 :         GDALCopyWordsFromT<double>(static_cast<double *>(pSrcData), nSrcPixelOffset, true,
    1296                 :                                  pDstData, eDstType, nDstPixelOffset,
    1297          168280 :                                  nWordCount);
    1298          168280 :         break;
    1299                 :     case GDT_Unknown:
    1300                 :     default:
    1301               0 :         CPLAssert(FALSE);
    1302                 :     }
    1303                 : 
    1304                 : #else // undefined USE_NEW_COPYWORDS
    1305                 : /* -------------------------------------------------------------------- */
    1306                 : /*      Special case when no data type translation is required.         */
    1307                 : /* -------------------------------------------------------------------- */
    1308                 :     if( eSrcType == eDstType )
    1309                 :     {
    1310                 :         int     nWordSize = GDALGetDataTypeSize(eSrcType)/8;
    1311                 :         int     i;
    1312                 : 
    1313                 :         // contiguous blocks.
    1314                 :         if( nWordSize == nSrcPixelOffset && nWordSize == nDstPixelOffset )
    1315                 :         {
    1316                 :             memcpy( pDstData, pSrcData, nSrcPixelOffset * nWordCount );
    1317                 :             return;
    1318                 :         }
    1319                 : 
    1320                 :         GByte *pabySrc = (GByte *) pSrcData;
    1321                 :         GByte *pabyDst = (GByte *) pDstData;
    1322                 : 
    1323                 :         // Moving single bytes.
    1324                 :         if( nWordSize == 1 )
    1325                 :         {
    1326                 :             if (nWordCount > 100)
    1327                 :             {
    1328                 : /* ==================================================================== */
    1329                 : /*     Optimization for high number of words to transfer and some       */
    1330                 : /*     typical source and destination pixel spacing : we unroll the     */
    1331                 : /*     loop.                                                            */
    1332                 : /* ==================================================================== */
    1333                 : #define ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, _k) \
    1334                 :                  pabyDst[_nDstPixelOffset * _k] = pabySrc[_nSrcPixelOffset * _k]
    1335                 : #define ASSIGN_LOOP(_nSrcPixelOffset, _nDstPixelOffset) \
    1336                 :                 for( i = nWordCount / 16 ; i != 0; i-- ) \
    1337                 :                 { \
    1338                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 0); \
    1339                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 1); \
    1340                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 2); \
    1341                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 3); \
    1342                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 4); \
    1343                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 5); \
    1344                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 6); \
    1345                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 7); \
    1346                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 8); \
    1347                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 9); \
    1348                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 10); \
    1349                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 11); \
    1350                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 12); \
    1351                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 13); \
    1352                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 14); \
    1353                 :                     ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 15); \
    1354                 :                     pabyDst += _nDstPixelOffset * 16; \
    1355                 :                     pabySrc += _nSrcPixelOffset * 16; \
    1356                 :                 } \
    1357                 :                 nWordCount = nWordCount % 16;
    1358                 : 
    1359                 :                 if (nSrcPixelOffset == 3 && nDstPixelOffset == 1)
    1360                 :                 {
    1361                 :                     ASSIGN_LOOP(3, 1)
    1362                 :                 }
    1363                 :                 else if (nSrcPixelOffset == 1 && nDstPixelOffset == 3)
    1364                 :                 {
    1365                 :                     ASSIGN_LOOP(1, 3)
    1366                 :                 }
    1367                 :                 else if (nSrcPixelOffset == 4 && nDstPixelOffset == 1)
    1368                 :                 {
    1369                 :                     ASSIGN_LOOP(4, 1)
    1370                 :                 }
    1371                 :                 else if (nSrcPixelOffset == 1 && nDstPixelOffset == 4)
    1372                 :                 {
    1373                 :                     ASSIGN_LOOP(1, 4)
    1374                 :                 }
    1375                 :                 else if (nSrcPixelOffset == 3 && nDstPixelOffset == 4)
    1376                 :                 {
    1377                 :                     ASSIGN_LOOP(3, 4)
    1378                 :                 }
    1379                 :                 else if (nSrcPixelOffset == 4 && nDstPixelOffset == 3)
    1380                 :                 {
    1381                 :                     ASSIGN_LOOP(4, 3)
    1382                 :                 }
    1383                 :             }
    1384                 : 
    1385                 :             for( i = nWordCount; i != 0; i-- )
    1386                 :             {
    1387                 :                 *pabyDst = *pabySrc;
    1388                 :                 pabyDst += nDstPixelOffset;
    1389                 :                 pabySrc += nSrcPixelOffset;
    1390                 :             }
    1391                 :         }
    1392                 :         else if (nWordSize == 2)
    1393                 :         {
    1394                 :             for( i = nWordCount; i != 0; i-- )
    1395                 :             {
    1396                 :                 *(short*)pabyDst = *(short*)pabySrc;
    1397                 :                 pabyDst += nDstPixelOffset;
    1398                 :                 pabySrc += nSrcPixelOffset;
    1399                 :             }
    1400                 :         }
    1401                 :         else if (nWordSize == 4)
    1402                 :         {
    1403                 :             for( i = nWordCount; i != 0; i-- )
    1404                 :             {
    1405                 :                 *(int*)pabyDst = *(int*)pabySrc;
    1406                 :                 pabyDst += nDstPixelOffset;
    1407                 :                 pabySrc += nSrcPixelOffset;
    1408                 :             }
    1409                 :         }
    1410                 :         else if (nWordSize == 8)
    1411                 :         {
    1412                 :             for( i = nWordCount; i != 0; i-- )
    1413                 :             {
    1414                 :                 ((int*)pabyDst)[0] = ((int*)pabySrc)[0];
    1415                 :                 ((int*)pabyDst)[1] = ((int*)pabySrc)[1];
    1416                 :                 pabyDst += nDstPixelOffset;
    1417                 :                 pabySrc += nSrcPixelOffset;
    1418                 :             }
    1419                 :         }
    1420                 :         else if (nWordSize == 16)
    1421                 :         {
    1422                 :             for( i = nWordCount; i != 0; i-- )
    1423                 :             {
    1424                 :                 ((int*)pabyDst)[0] = ((int*)pabySrc)[0];
    1425                 :                 ((int*)pabyDst)[1] = ((int*)pabySrc)[1];
    1426                 :                 ((int*)pabyDst)[2] = ((int*)pabySrc)[2];
    1427                 :                 ((int*)pabyDst)[3] = ((int*)pabySrc)[3];
    1428                 :                 pabyDst += nDstPixelOffset;
    1429                 :                 pabySrc += nSrcPixelOffset;
    1430                 :             }
    1431                 :         }
    1432                 :         else
    1433                 :         {
    1434                 :             CPLAssert(FALSE);
    1435                 :         }
    1436                 : 
    1437                 :         return;
    1438                 :     }
    1439                 :     
    1440                 : /* ==================================================================== */
    1441                 : /*      General translation case                                        */
    1442                 : /* ==================================================================== */
    1443                 :     for( int iWord = 0; iWord < nWordCount; iWord++ )
    1444                 :     {
    1445                 :         void   *pSrcWord, *pDstWord;
    1446                 :         double  dfPixelValue=0.0, dfPixelValueI=0.0;
    1447                 : 
    1448                 :         pSrcWord = static_cast<GByte *>(pSrcData) + iWord * nSrcPixelOffset;
    1449                 :         pDstWord = static_cast<GByte *>(pDstData) + iWord * nDstPixelOffset;
    1450                 : 
    1451                 : /* -------------------------------------------------------------------- */
    1452                 : /*      Fetch source value based on data type.                          */
    1453                 : /* -------------------------------------------------------------------- */
    1454                 :         switch( eSrcType )
    1455                 :         {
    1456                 :           case GDT_Byte:
    1457                 :           {
    1458                 :               GByte byVal = *static_cast<GByte *>(pSrcWord);
    1459                 :               switch( eDstType )
    1460                 :               {
    1461                 :                 case GDT_UInt16:
    1462                 :                   *static_cast<GUInt16 *>(pDstWord) = byVal;
    1463                 :                   continue;
    1464                 :                 case GDT_Int16:
    1465                 :                   *static_cast<GInt16 *>(pDstWord) = byVal;
    1466                 :                   continue;
    1467                 :                 case GDT_UInt32:
    1468                 :                   *static_cast<GUInt32 *>(pDstWord) = byVal;
    1469                 :                   continue;
    1470                 :                 case GDT_Int32:
    1471                 :                   *static_cast<GInt32 *>(pDstWord) = byVal;
    1472                 :                   continue;
    1473                 :                 case GDT_CInt16:
    1474                 :                 {
    1475                 :                     GInt16 *panDstWord = static_cast<GInt16 *>(pDstWord);
    1476                 :                     panDstWord[0] = byVal;
    1477                 :                     panDstWord[1] = 0;
    1478                 :                     continue;
    1479                 :                 }
    1480                 :                 case GDT_CInt32:
    1481                 :                 {
    1482                 :                     GInt32 *panDstWord = static_cast<GInt32 *>(pDstWord);
    1483                 :                     panDstWord[0] = byVal;
    1484                 :                     panDstWord[1] = 0;
    1485                 :                     continue;
    1486                 :                 }
    1487                 :                 default:
    1488                 :                   break;
    1489                 :               }
    1490                 :               dfPixelValue = byVal;
    1491                 :           }
    1492                 :           break;
    1493                 : 
    1494                 :           case GDT_UInt16:
    1495                 :           {
    1496                 :               GUInt16 nVal = *static_cast<GUInt16 *>(pSrcWord);
    1497                 :               switch( eDstType )
    1498                 :               {
    1499                 :                 case GDT_Byte:
    1500                 :                 {
    1501                 :                     GByte byVal;
    1502                 :                     if( nVal > 255 )
    1503                 :                         byVal = 255;
    1504                 :                     else
    1505                 :                         byVal = static_cast<GByte>(nVal);
    1506                 :                     *static_cast<GByte *>(pDstWord) = byVal;
    1507                 :                     continue;
    1508                 :                 }
    1509                 :                 case GDT_Int16:
    1510                 :                   if( nVal > 32767 )
    1511                 :                       nVal = 32767;
    1512                 :                   *static_cast<GInt16 *>(pDstWord) = nVal;
    1513                 :                   continue;
    1514                 :                 case GDT_UInt32:
    1515                 :                   *static_cast<GUInt32 *>(pDstWord) = nVal;
    1516                 :                   continue;
    1517                 :                 case GDT_Int32:
    1518                 :                   *static_cast<GInt32 *>(pDstWord) = nVal;
    1519                 :                   continue;
    1520                 :                 case GDT_CInt16:
    1521                 :                 {
    1522                 :                     GInt16 *panDstWord = static_cast<GInt16 *>(pDstWord);
    1523                 :                     if( nVal > 32767 )
    1524                 :                         nVal = 32767;
    1525                 :                     panDstWord[0] = nVal;
    1526                 :                     panDstWord[1] = 0;
    1527                 :                     continue;
    1528                 :                 }
    1529                 :                 case GDT_CInt32:
    1530                 :                 {
    1531                 :                     GInt32 *panDstWord = static_cast<GInt32 *>(pDstWord);
    1532                 :                     panDstWord[0] = nVal;
    1533                 :                     panDstWord[1] = 0;
    1534                 :                     continue;
    1535                 :                 }
    1536                 :                 default:
    1537                 :                   break;
    1538                 :               }
    1539                 :               dfPixelValue = nVal;
    1540                 :           }
    1541                 :           break;
    1542                 :           
    1543                 :           case GDT_Int16:
    1544                 :           {
    1545                 :               GInt16 nVal = *static_cast<GInt16 *>(pSrcWord);
    1546                 :               switch( eDstType )
    1547                 :               {
    1548                 :                 case GDT_Byte:
    1549                 :                 {
    1550                 :                     GByte byVal;
    1551                 :                     if( nVal > 255 )
    1552                 :                         byVal = 255;
    1553                 :                     else if (nVal < 0)
    1554                 :                         byVal = 0;
    1555                 :                     else
    1556                 :                         byVal = static_cast<GByte>(nVal);
    1557                 :                     *static_cast<GByte *>(pDstWord) = byVal;
    1558                 :                     continue;
    1559                 :                 }
    1560                 :                 case GDT_UInt16:
    1561                 :                   if( nVal < 0 )
    1562                 :                       nVal = 0;
    1563                 :                   *static_cast<GUInt16 *>(pDstWord) = nVal;
    1564                 :                   continue;
    1565                 :                 case GDT_UInt32:
    1566                 :                   if( nVal < 0 )
    1567                 :                       nVal = 0;
    1568                 :                   *static_cast<GUInt32 *>(pDstWord) = nVal;
    1569                 :                   continue;
    1570                 :                 case GDT_Int32:
    1571                 :                   *static_cast<GInt32 *>(pDstWord) = nVal;
    1572                 :                   continue;
    1573                 :                 case GDT_CInt16:
    1574                 :                 {
    1575                 :                     GInt16 *panDstWord = static_cast<GInt16 *>(pDstWord);
    1576                 :                     panDstWord[0] = nVal;
    1577                 :                     panDstWord[1] = 0;
    1578                 :                     continue;
    1579                 :                 }
    1580                 :                 case GDT_CInt32:
    1581                 :                 {
    1582                 :                     GInt32 *panDstWord = static_cast<GInt32 *>(pDstWord);
    1583                 :                     panDstWord[0] = nVal;
    1584                 :                     panDstWord[1] = 0;
    1585                 :                     continue;
    1586                 :                 }
    1587                 :                 default:
    1588                 :                   break;
    1589                 :               }
    1590                 :               dfPixelValue = nVal;
    1591                 :           }
    1592                 :           break;
    1593                 :           
    1594                 :           case GDT_Int32:
    1595                 :           {
    1596                 :               GInt32 nVal = *static_cast<GInt32 *>(pSrcWord);
    1597                 :               switch( eDstType )
    1598                 :               {
    1599                 :                 case GDT_Byte:
    1600                 :                 {
    1601                 :                     GByte byVal;
    1602                 :                     if( nVal > 255 )
    1603                 :                         byVal = 255;
    1604                 :                     else if (nVal < 0)
    1605                 :                         byVal = 0;
    1606                 :                     else
    1607                 :                         byVal = nVal;
    1608                 :                     *static_cast<GByte *>(pDstWord) = byVal;
    1609                 :                     continue;
    1610                 :                 }
    1611                 :                 case GDT_UInt16:
    1612                 :                   if( nVal > 65535 )
    1613                 :                       nVal = 65535;
    1614                 :                   else if( nVal < 0 )
    1615                 :                       nVal = 0;
    1616                 :                   *static_cast<GUInt16 *>(pDstWord) = nVal;
    1617                 :                   continue;
    1618                 :                 case GDT_Int16:
    1619                 :                   if( nVal > 32767 )
    1620                 :                       nVal = 32767;
    1621                 :                   else if( nVal < -32768)
    1622                 :                       nVal = -32768;
    1623                 :                   *static_cast<GInt16 *>(pDstWord) = nVal;
    1624                 :                   continue;
    1625                 :                 case GDT_UInt32:
    1626                 :                   if( nVal < 0 )
    1627                 :                       nVal = 0;
    1628                 :                   *static_cast<GUInt32 *>(pDstWord) = nVal;
    1629                 :                   continue;
    1630                 :                 case GDT_CInt16:
    1631                 :                 {
    1632                 :                     GInt16 *panDstWord = static_cast<GInt16 *>(pDstWord);
    1633                 :                     if( nVal > 32767 )
    1634                 :                         nVal = 32767;
    1635                 :                     else if( nVal < -32768)
    1636                 :                         nVal = -32768;
    1637                 :                     panDstWord[0] = nVal;
    1638                 :                     panDstWord[1] = 0;
    1639                 :                     continue;
    1640                 :                 }
    1641                 :                 case GDT_CInt32:
    1642                 :                 {
    1643                 :                     GInt32 *panDstWord = static_cast<GInt32 *>(pDstWord);
    1644                 :                     panDstWord[0] = nVal;
    1645                 :                     panDstWord[1] = 0;
    1646                 :                     continue;
    1647                 :                 }
    1648                 :                 default:
    1649                 :                   break;
    1650                 :               }
    1651                 :               dfPixelValue = nVal;
    1652                 :           }
    1653                 :           break;
    1654                 :           
    1655                 :           case GDT_UInt32:
    1656                 :           {
    1657                 :               GUInt32 nVal = *static_cast<GUInt32 *>(pSrcWord);
    1658                 :               switch( eDstType )
    1659                 :               {
    1660                 :                 case GDT_Byte:
    1661                 :                 {
    1662                 :                     GByte byVal;
    1663                 :                     if( nVal > 255 )
    1664                 :                         byVal = 255;
    1665                 :                     else
    1666                 :                         byVal = nVal;
    1667                 :                     *static_cast<GByte *>(pDstWord) = byVal;
    1668                 :                     continue;
    1669                 :                 }
    1670                 :                 case GDT_UInt16:
    1671                 :                   if( nVal > 65535 )
    1672                 :                       nVal = 65535;
    1673                 :                   *static_cast<GUInt16 *>(pDstWord) = nVal;
    1674                 :                   continue;
    1675                 :                 case GDT_Int16:
    1676                 :                   if( nVal > 32767 )
    1677                 :                       nVal = 32767;
    1678                 :                   *static_cast<GInt16 *>(pDstWord) = nVal;
    1679                 :                   continue;
    1680                 :                 case GDT_Int32:
    1681                 :                   if( nVal > 2147483647UL )
    1682                 :                       nVal = 2147483647UL;
    1683                 :                   *static_cast<GInt32 *>(pDstWord) = nVal;
    1684                 :                   continue;
    1685                 :                 case GDT_CInt16:
    1686                 :                 {
    1687                 :                     GInt16 *panDstWord = static_cast<GInt16 *>(pDstWord);
    1688                 :                     if( nVal > 32767 )
    1689                 :                         nVal = 32767;
    1690                 :                     panDstWord[0] = nVal;
    1691                 :                     panDstWord[1] = 0;
    1692                 :                     continue;
    1693                 :                 }
    1694                 :                 case GDT_CInt32:
    1695                 :                 {
    1696                 :                     GInt32 *panDstWord = static_cast<GInt32 *>(pDstWord);
    1697                 :                     if( nVal > 2147483647UL )
    1698                 :                         nVal = 2147483647UL;
    1699                 :                     panDstWord[0] = nVal;
    1700                 :                     panDstWord[1] = 0;
    1701                 :                     continue;
    1702                 :                 }
    1703                 :                 default:
    1704                 :                   break;
    1705                 :               }
    1706                 :               dfPixelValue = nVal;
    1707                 :           }
    1708                 :           break;
    1709                 :           
    1710                 :           case GDT_CInt16:
    1711                 :           {
    1712                 :               GInt16 *panSrcWord = static_cast<GInt16 *>(pSrcWord);
    1713                 :               GInt16 nVal = panSrcWord[0];
    1714                 :               switch( eDstType )
    1715                 :               {
    1716                 :                 case GDT_Byte:
    1717                 :                 {
    1718                 :                     GByte byVal;
    1719                 :                     if( nVal > 255 )
    1720                 :                         byVal = 255;
    1721                 :                     else if (nVal < 0)
    1722                 :                         byVal = 0;
    1723                 :                     else
    1724                 :                         byVal = static_cast<GByte>(nVal);
    1725                 :                     *static_cast<GByte *>(pDstWord) = byVal;
    1726                 :                     continue;
    1727                 :                 }
    1728                 :                 case GDT_Int16:
    1729                 :                   *static_cast<GInt16 *>(pDstWord) = nVal;
    1730                 :                   continue;
    1731                 :                 case GDT_UInt16:
    1732                 :                   if( nVal < 0 )
    1733                 :                       nVal = 0;
    1734                 :                   *static_cast<GUInt16 *>(pDstWord) = nVal;
    1735                 :                   continue;
    1736                 :                 case GDT_UInt32:
    1737                 :                   if( nVal < 0 )
    1738                 :                       nVal = 0;
    1739                 :                   *static_cast<GUInt32 *>(pDstWord) = nVal;
    1740                 :                   continue;
    1741                 :                 case GDT_Int32:
    1742                 :                   *static_cast<GInt32 *>(pDstWord) = nVal;
    1743                 :                   continue;
    1744                 :                 case GDT_CInt32:
    1745                 :                 {
    1746                 :                     GInt32 *panDstWord = static_cast<GInt32 *>(pDstWord);
    1747                 :                     panDstWord[0] = panSrcWord[0];
    1748                 :                     panDstWord[1] = panSrcWord[1];
    1749                 :                     continue;
    1750                 :                 }
    1751                 :                 default:
    1752                 :                   break;
    1753                 :               }
    1754                 :               dfPixelValue = panSrcWord[0];
    1755                 :               dfPixelValueI = panSrcWord[1];
    1756                 :           }
    1757                 :           break;
    1758                 :           
    1759                 :           case GDT_CInt32:
    1760                 :           {
    1761                 :               GInt32 *panSrcWord = static_cast<GInt32 *>(pSrcWord);
    1762                 :               GInt32 nVal = panSrcWord[0];
    1763                 :               switch( eDstType )
    1764                 :               {
    1765                 :                 case GDT_Byte:
    1766                 :                 {
    1767                 :                     GByte byVal;
    1768                 :                     if( nVal > 255 )
    1769                 :                         byVal = 255;
    1770                 :                     else if (nVal < 0)
    1771                 :                         byVal = 0;
    1772                 :                     else
    1773                 :                         byVal = nVal;
    1774                 :                     *static_cast<GByte *>(pDstWord) = byVal;
    1775                 :                     continue;
    1776                 :                 }
    1777                 :                 case GDT_Int16:
    1778                 :                   if( nVal > 32767 )
    1779                 :                       nVal = 32767;
    1780                 :                   else if( nVal < -32768)
    1781                 :                       nVal = -32768;
    1782                 :                   *static_cast<GInt16 *>(pDstWord) = nVal;
    1783                 :                   continue;
    1784                 :                 case GDT_UInt16:
    1785                 :                   if( nVal > 65535 )
    1786                 :                       nVal = 65535;
    1787                 :                   else if( nVal < 0 )
    1788                 :                       nVal = 0;
    1789                 :                   *static_cast<GUInt16 *>(pDstWord) = nVal;
    1790                 :                   continue;
    1791                 :                 case GDT_UInt32:
    1792                 :                   if( nVal < 0 )
    1793                 :                       nVal = 0;
    1794                 :                   *static_cast<GUInt32 *>(pDstWord) = nVal;
    1795                 :                   continue;
    1796                 :                 case GDT_Int32:
    1797                 :                   *static_cast<GInt32 *>(pDstWord) = nVal;
    1798                 :                   continue;
    1799                 :                 case GDT_CInt16:
    1800                 :                 {
    1801                 :                     GInt16 *panDstWord = static_cast<GInt16 *>(pDstWord);
    1802                 :                     if( nVal > 32767 )
    1803                 :                         nVal = 32767;
    1804                 :                     else if( nVal < -32768)
    1805                 :                         nVal = -32768;
    1806                 :                     panDstWord[0] = nVal;
    1807                 :                     nVal = panSrcWord[1];
    1808                 :                     if( nVal > 32767 )
    1809                 :                         nVal = 32767;
    1810                 :                     else if( nVal < -32768)
    1811                 :                         nVal = -32768;
    1812                 :                     panDstWord[1] = nVal;
    1813                 :                     continue;
    1814                 :                 }
    1815                 :                 default:
    1816                 :                   break;
    1817                 :               }
    1818                 :               dfPixelValue = panSrcWord[0];
    1819                 :               dfPixelValueI = panSrcWord[1];
    1820                 :           }
    1821                 :           break;
    1822                 : 
    1823                 :           case GDT_Float32:
    1824                 :           {
    1825                 :               float fVal = *static_cast<float *>(pSrcWord);
    1826                 :               dfPixelValue = fVal;
    1827                 :           }
    1828                 :           break;
    1829                 :           
    1830                 :           case GDT_Float64:
    1831                 :           {
    1832                 :               dfPixelValue = *static_cast<double *>(pSrcWord);
    1833                 :           }
    1834                 :           break;
    1835                 : 
    1836                 :           case GDT_CFloat32:
    1837                 :           {
    1838                 :               float *pafSrcWord = static_cast<float *>(pSrcWord);
    1839                 :               dfPixelValue = pafSrcWord[0];
    1840                 :               dfPixelValueI = pafSrcWord[1];
    1841                 :           }
    1842                 :           break;
    1843                 :           
    1844                 :           case GDT_CFloat64:
    1845                 :           {
    1846                 :               double *padfSrcWord = static_cast<double *>(pSrcWord);
    1847                 :               dfPixelValue = padfSrcWord[0];
    1848                 :               dfPixelValueI = padfSrcWord[1];
    1849                 :           }
    1850                 :           break;
    1851                 : 
    1852                 :           default:
    1853                 :             CPLAssert( FALSE );
    1854                 :         }
    1855                 :         
    1856                 : /* -------------------------------------------------------------------- */
    1857                 : /*      Set the destination pixel, doing range clipping as needed.      */
    1858                 : /* -------------------------------------------------------------------- */
    1859                 :         switch( eDstType )
    1860                 :         {
    1861                 :           case GDT_Byte:
    1862                 :           {
    1863                 :               GByte *pabyDstWord = static_cast<GByte *>(pDstWord);
    1864                 : 
    1865                 :               dfPixelValue += (float) 0.5;
    1866                 : 
    1867                 :               if( dfPixelValue < 0.0 )
    1868                 :                   *pabyDstWord = 0;
    1869                 :               else if( dfPixelValue > 255.0 )
    1870                 :                   *pabyDstWord = 255;
    1871                 :               else
    1872                 :                   *pabyDstWord = (GByte) dfPixelValue;
    1873                 :           }
    1874                 :           break;
    1875                 : 
    1876                 :           case GDT_UInt16:
    1877                 :           {
    1878                 :               GUInt16   nVal;
    1879                 :               
    1880                 :               dfPixelValue += 0.5;
    1881                 : 
    1882                 :               if( dfPixelValue < 0.0 )
    1883                 :                   nVal = 0;
    1884                 :               else if( dfPixelValue > 65535.0 )
    1885                 :                   nVal = 65535;
    1886                 :               else
    1887                 :                   nVal = (GUInt16) dfPixelValue;
    1888                 : 
    1889                 :               *static_cast<GUInt16 *>(pDstWord) = nVal;
    1890                 :           }
    1891                 :           break;
    1892                 : 
    1893                 :           case GDT_Int16:
    1894                 :           {
    1895                 :               GInt16    nVal;
    1896                 :               
    1897                 :               dfPixelValue += 0.5;
    1898                 : 
    1899                 :               if( dfPixelValue < -32768 )
    1900                 :                   nVal = -32768;
    1901                 :               else if( dfPixelValue > 32767 )
    1902                 :                   nVal = 32767;
    1903                 :               else
    1904                 :                   nVal = (GInt16) floor(dfPixelValue);
    1905                 : 
    1906                 :               *static_cast<GInt16 *>(pDstWord) = nVal;
    1907                 :           }
    1908                 :           break;
    1909                 :           
    1910                 :           case GDT_UInt32:
    1911                 :           {
    1912                 :               GUInt32   nVal;
    1913                 :               
    1914                 :               dfPixelValue += 0.5;
    1915                 : 
    1916                 :               if( dfPixelValue < 0 )
    1917                 :                   nVal = 0;
    1918                 :               else if( dfPixelValue > 4294967295U )
    1919                 :                   nVal = 4294967295U;
    1920                 :               else
    1921                 :                   nVal = (GInt32) dfPixelValue;
    1922                 : 
    1923                 :               *static_cast<GUInt32 *>(pDstWord) = nVal;
    1924                 :           }
    1925                 :           break;
    1926                 :           
    1927                 :           case GDT_Int32:
    1928                 :           {
    1929                 :               GInt32    nVal;
    1930                 :               
    1931                 :               dfPixelValue += 0.5;
    1932                 : 
    1933                 :               if( dfPixelValue < -2147483648.0 )
    1934                 :                   nVal = INT_MIN;
    1935                 :               else if( dfPixelValue > 2147483647 )
    1936                 :                   nVal = 2147483647;
    1937                 :               else
    1938                 :                   nVal = (GInt32) floor(dfPixelValue);
    1939                 : 
    1940                 :               *static_cast<GInt32 *>(pDstWord) = nVal;
    1941                 :           }
    1942                 :           break;
    1943                 : 
    1944                 :           case GDT_Float32:
    1945                 :           {
    1946                 :               *static_cast<float *>(pDstWord) = static_cast<float>(dfPixelValue);
    1947                 :           }
    1948                 :           break;
    1949                 : 
    1950                 :           case GDT_Float64:
    1951                 :             *static_cast<double *>(pDstWord) = dfPixelValue;
    1952                 :             break;
    1953                 :               
    1954                 :           case GDT_CInt16:
    1955                 :           {
    1956                 :               GInt16    nVal;
    1957                 :               GInt16 *panDstWord = static_cast<GInt16 *>(pDstWord);
    1958                 :               
    1959                 :               dfPixelValue += 0.5;
    1960                 :               dfPixelValueI += 0.5;
    1961                 : 
    1962                 :               if( dfPixelValue < -32768 )
    1963                 :                   nVal = -32768;
    1964                 :               else if( dfPixelValue > 32767 )
    1965                 :                   nVal = 32767;
    1966                 :               else
    1967                 :                   nVal = (GInt16) floor(dfPixelValue);
    1968                 :               panDstWord[0] = nVal;
    1969                 : 
    1970                 :               if( dfPixelValueI < -32768 )
    1971                 :                   nVal = -32768;
    1972                 :               else if( dfPixelValueI > 32767 )
    1973                 :                   nVal = 32767;
    1974                 :               else
    1975                 :                   nVal = (GInt16) floor(dfPixelValueI);
    1976                 :               panDstWord[1] = nVal;
    1977                 :           }
    1978                 :           break;
    1979                 :           
    1980                 :           case GDT_CInt32:
    1981                 :           {
    1982                 :               GInt32    nVal;
    1983                 :               GInt32 *panDstWord = static_cast<GInt32 *>(pDstWord);
    1984                 :               
    1985                 :               dfPixelValue += 0.5;
    1986                 :               dfPixelValueI += 0.5;
    1987                 : 
    1988                 :               if( dfPixelValue < -2147483648.0 )
    1989                 :                   nVal = INT_MIN;
    1990                 :               else if( dfPixelValue > 2147483647 )
    1991                 :                   nVal = 2147483647;
    1992                 :               else
    1993                 :                   nVal = (GInt32) floor(dfPixelValue);
    1994                 : 
    1995                 :               panDstWord[0] = nVal;
    1996                 : 
    1997                 :               if( dfPixelValueI < -2147483648.0 )
    1998                 :                   nVal = INT_MIN;
    1999                 :               else if( dfPixelValueI > 2147483647 )
    2000                 :                   nVal = 2147483647;
    2001                 :               else
    2002                 :                   nVal = (GInt32) floor(dfPixelValueI);
    2003                 : 
    2004                 :               panDstWord[1] = nVal;
    2005                 :           }
    2006                 :           break;
    2007                 : 
    2008                 :           case GDT_CFloat32:
    2009                 :           {
    2010                 :               float *pafDstWord = static_cast<float *>(pDstWord);
    2011                 :               pafDstWord[0] = static_cast<float>(dfPixelValue);
    2012                 :               pafDstWord[1] = static_cast<float>(dfPixelValueI);
    2013                 :           }
    2014                 :           break;
    2015                 : 
    2016                 :           case GDT_CFloat64:
    2017                 :           {
    2018                 :               double *padfDstWord = static_cast<double *>(pDstWord);
    2019                 :               padfDstWord[0] = dfPixelValue;
    2020                 :               padfDstWord[1] = dfPixelValueI;
    2021                 :           }
    2022                 :           break;
    2023                 :               
    2024                 :           default:
    2025                 :             CPLAssert( FALSE );
    2026                 :         }
    2027                 :     } /* next iWord */
    2028                 : #endif // defined USE_NEW_COPYWORDS
    2029                 : }
    2030                 : 
    2031                 : /************************************************************************/
    2032                 : /*                            GDALCopyBits()                            */
    2033                 : /************************************************************************/
    2034                 : 
    2035                 : /**
    2036                 :  * Bitwise word copying.
    2037                 :  *
    2038                 :  * A function for moving sets of partial bytes around.  Loosely
    2039                 :  * speaking this is a bitswise analog to GDALCopyWords().
    2040                 :  *
    2041                 :  * It copies nStepCount "words" where each word is nBitCount bits long. 
    2042                 :  * The nSrcStep and nDstStep are the number of bits from the start of one
    2043                 :  * word to the next (same as nBitCount if they are packed).  The nSrcOffset
    2044                 :  * and nDstOffset are the offset into the source and destination buffers
    2045                 :  * to start at, also measured in bits. 
    2046                 :  *
    2047                 :  * All bit offsets are assumed to start from the high order bit in a byte
    2048                 :  * (ie. most significant bit first).  Currently this function is not very
    2049                 :  * optimized, but it may be improved for some common cases in the future 
    2050                 :  * as needed. 
    2051                 :  *
    2052                 :  * @param pabySrcData the source data buffer.
    2053                 :  * @param nSrcOffset the offset (in bits) in pabySrcData to the start of the 
    2054                 :  * first word to copy.
    2055                 :  * @param nSrcStep the offset in bits from the start one source word to the 
    2056                 :  * start of the next. 
    2057                 :  * @param pabyDstData the destination data buffer.
    2058                 :  * @param nDstOffset the offset (in bits) in pabyDstData to the start of the 
    2059                 :  * first word to copy over.
    2060                 :  * @param nDstStep the offset in bits from the start one word to the 
    2061                 :  * start of the next. 
    2062                 :  * @param nBitCount the number of bits in a word to be copied.
    2063                 :  * @param nStepCount the number of words to copy.
    2064                 :  */
    2065                 : 
    2066               0 : void GDALCopyBits( const GByte *pabySrcData, int nSrcOffset, int nSrcStep, 
    2067                 :                    GByte *pabyDstData, int nDstOffset, int nDstStep,
    2068                 :                    int nBitCount, int nStepCount )
    2069                 : 
    2070                 : {
    2071               0 :     VALIDATE_POINTER0( pabySrcData, "GDALCopyBits" );
    2072                 : 
    2073                 :     int iStep;
    2074                 :     int iBit;
    2075                 : 
    2076               0 :     for( iStep = 0; iStep < nStepCount; iStep++ )
    2077                 :     {
    2078               0 :         for( iBit = 0; iBit < nBitCount; iBit++ )
    2079                 :         {
    2080               0 :             if( pabySrcData[nSrcOffset>>3] 
    2081                 :                 & (0x80 >>(nSrcOffset & 7)) )
    2082               0 :                 pabyDstData[nDstOffset>>3] |= (0x80 >> (nDstOffset & 7));
    2083                 :             else
    2084               0 :                 pabyDstData[nDstOffset>>3] &= ~(0x80 >> (nDstOffset & 7));
    2085                 : 
    2086                 : 
    2087               0 :             nSrcOffset++;
    2088               0 :             nDstOffset++;
    2089                 :         } 
    2090                 : 
    2091               0 :         nSrcOffset += (nSrcStep - nBitCount);
    2092               0 :         nDstOffset += (nDstStep - nBitCount);
    2093                 :     }
    2094                 : }
    2095                 : 
    2096                 : /************************************************************************/
    2097                 : /*                    GDALGetBestOverviewLevel()                        */
    2098                 : /*                                                                      */
    2099                 : /* Returns the best overview level to satisfy the query or -1 if none   */
    2100                 : /* Also updates nXOff, nYOff, nXSize, nYSize when returning a valid     */
    2101                 : /* overview level                                                       */
    2102                 : /************************************************************************/
    2103                 : 
    2104              15 : int GDALBandGetBestOverviewLevel(GDALRasterBand* poBand,
    2105                 :                                  int &nXOff, int &nYOff,
    2106                 :                                  int &nXSize, int &nYSize,
    2107                 :                                  int nBufXSize, int nBufYSize)
    2108                 : {
    2109                 :     double dfDesiredResolution;
    2110                 : /* -------------------------------------------------------------------- */
    2111                 : /*      Compute the desired resolution.  The resolution is              */
    2112                 : /*      based on the least reduced axis, and represents the number      */
    2113                 : /*      of source pixels to one destination pixel.                      */
    2114                 : /* -------------------------------------------------------------------- */
    2115              15 :     if( (nXSize / (double) nBufXSize) < (nYSize / (double) nBufYSize ) 
    2116                 :         || nBufYSize == 1 )
    2117               0 :         dfDesiredResolution = nXSize / (double) nBufXSize;
    2118                 :     else
    2119              15 :         dfDesiredResolution = nYSize / (double) nBufYSize;
    2120                 : 
    2121                 : /* -------------------------------------------------------------------- */
    2122                 : /*      Find the overview level that largest resolution value (most     */
    2123                 : /*      downsampled) that is still less than (or only a little more)    */
    2124                 : /*      downsampled than the request.                                   */
    2125                 : /* -------------------------------------------------------------------- */
    2126              15 :     int nOverviewCount = poBand->GetOverviewCount();
    2127              15 :     GDALRasterBand* poBestOverview = NULL;
    2128              15 :     double dfBestResolution = 0;
    2129              15 :     int nBestOverviewLevel = -1;
    2130                 :     
    2131              91 :     for( int iOverview = 0; iOverview < nOverviewCount; iOverview++ )
    2132                 :     {
    2133              76 :         GDALRasterBand  *poOverview = poBand->GetOverview( iOverview );
    2134              76 :         if (poOverview == NULL)
    2135               0 :             continue;
    2136                 : 
    2137                 :         double          dfResolution;
    2138                 : 
    2139                 :         // What resolution is this?
    2140              76 :         if( (poBand->GetXSize() / (double) poOverview->GetXSize())
    2141                 :             < (poBand->GetYSize() / (double) poOverview->GetYSize()) )
    2142                 :             dfResolution = 
    2143               0 :                 poBand->GetXSize() / (double) poOverview->GetXSize();
    2144                 :         else
    2145                 :             dfResolution = 
    2146              76 :                 poBand->GetYSize() / (double) poOverview->GetYSize();
    2147                 : 
    2148                 :         // Is it nearly the requested resolution and better (lower) than
    2149                 :         // the current best resolution?
    2150              76 :         if( dfResolution >= dfDesiredResolution * 1.2 
    2151                 :             || dfResolution <= dfBestResolution )
    2152               0 :             continue;
    2153                 : 
    2154                 :         // Ignore AVERAGE_BIT2GRAYSCALE overviews for RasterIO purposes.
    2155                 :         const char *pszResampling = 
    2156              76 :             poOverview->GetMetadataItem( "RESAMPLING" );
    2157                 : 
    2158              76 :         if( pszResampling != NULL && EQUALN(pszResampling,"AVERAGE_BIT2",12))
    2159               8 :             continue;
    2160                 : 
    2161                 :         // OK, this is our new best overview.
    2162              68 :         poBestOverview = poOverview;
    2163              68 :         nBestOverviewLevel = iOverview;
    2164              68 :         dfBestResolution = dfResolution;
    2165                 :     }
    2166                 : 
    2167                 : /* -------------------------------------------------------------------- */
    2168                 : /*      If we didn't find an overview that helps us, just return        */
    2169                 : /*      indicating failure and the full resolution image will be used.  */
    2170                 : /* -------------------------------------------------------------------- */
    2171              15 :     if( nBestOverviewLevel < 0 )
    2172               4 :         return -1;
    2173                 : 
    2174                 : /* -------------------------------------------------------------------- */
    2175                 : /*      Recompute the source window in terms of the selected            */
    2176                 : /*      overview.                                                       */
    2177                 : /* -------------------------------------------------------------------- */
    2178                 :     int         nOXOff, nOYOff, nOXSize, nOYSize;
    2179                 :     double      dfXRes, dfYRes;
    2180                 :     
    2181              11 :     dfXRes = poBand->GetXSize() / (double) poBestOverview->GetXSize();
    2182              11 :     dfYRes = poBand->GetYSize() / (double) poBestOverview->GetYSize();
    2183                 : 
    2184              11 :     nOXOff = MIN(poBestOverview->GetXSize()-1,(int) (nXOff/dfXRes+0.5));
    2185              11 :     nOYOff = MIN(poBestOverview->GetYSize()-1,(int) (nYOff/dfYRes+0.5));
    2186              11 :     nOXSize = MAX(1,(int) (nXSize/dfXRes + 0.5));
    2187              11 :     nOYSize = MAX(1,(int) (nYSize/dfYRes + 0.5));
    2188              11 :     if( nOXOff + nOXSize > poBestOverview->GetXSize() )
    2189               0 :         nOXSize = poBestOverview->GetXSize() - nOXOff;
    2190              11 :     if( nOYOff + nOYSize > poBestOverview->GetYSize() )
    2191               0 :         nOYSize = poBestOverview->GetYSize() - nOYOff;
    2192                 :         
    2193              11 :     nXOff = nOXOff;
    2194              11 :     nYOff = nOYOff;
    2195              11 :     nXSize = nOXSize;
    2196              11 :     nYSize = nOYSize;
    2197                 :     
    2198              11 :     return nBestOverviewLevel;
    2199                 : }
    2200                 : 
    2201                 : 
    2202                 : /************************************************************************/
    2203                 : /*                          OverviewRasterIO()                          */
    2204                 : /*                                                                      */
    2205                 : /*      Special work function to utilize available overviews to         */
    2206                 : /*      more efficiently satisfy downsampled requests.  It will         */
    2207                 : /*      return CE_Failure if there are no appropriate overviews         */
    2208                 : /*      available but it doesn't emit any error messages.               */
    2209                 : /************************************************************************/
    2210                 : 
    2211               0 : CPLErr GDALRasterBand::OverviewRasterIO( GDALRWFlag eRWFlag,
    2212                 :                                 int nXOff, int nYOff, int nXSize, int nYSize,
    2213                 :                                 void * pData, int nBufXSize, int nBufYSize,
    2214                 :                                 GDALDataType eBufType,
    2215                 :                                 int nPixelSpace, int nLineSpace )
    2216                 : 
    2217                 : 
    2218                 : {
    2219                 :     int         nOverview;
    2220                 : 
    2221                 :     nOverview =
    2222                 :         GDALBandGetBestOverviewLevel(this, nXOff, nYOff, nXSize, nYSize,
    2223               0 :                                      nBufXSize, nBufYSize);
    2224               0 :     if (nOverview < 0)
    2225               0 :         return CE_Failure;
    2226                 :         
    2227                 : /* -------------------------------------------------------------------- */
    2228                 : /*      Recast the call in terms of the new raster layer.               */
    2229                 : /* -------------------------------------------------------------------- */
    2230               0 :     GDALRasterBand* poOverviewBand = GetOverview(nOverview);
    2231               0 :     if (poOverviewBand == NULL)
    2232               0 :         return CE_Failure;
    2233                 : 
    2234                 :     return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
    2235                 :                                      pData, nBufXSize, nBufYSize, eBufType,
    2236               0 :                                      nPixelSpace, nLineSpace );
    2237                 : }
    2238                 : 
    2239                 : /************************************************************************/
    2240                 : /*                        GetBestOverviewLevel()                        */
    2241                 : /*                                                                      */
    2242                 : /* Returns the best overview level to satisfy the query or -1 if none   */
    2243                 : /* Also updates nXOff, nYOff, nXSize, nYSize when returning a valid     */
    2244                 : /* overview level                                                       */
    2245                 : /************************************************************************/
    2246                 : 
    2247                 : static
    2248               2 : int GDALDatasetGetBestOverviewLevel(GDALDataset* poDS,
    2249                 :                                     int &nXOff, int &nYOff,
    2250                 :                                     int &nXSize, int &nYSize,
    2251                 :                                     int nBufXSize, int nBufYSize,
    2252                 :                                     int nBandCount, int *panBandMap)
    2253                 : {
    2254                 :     int iBand, iOverview;
    2255               2 :     int nOverviewCount = 0;
    2256               2 :     GDALRasterBand *poFirstBand = NULL;
    2257                 :     
    2258               2 :     if (nBandCount == 0)
    2259               0 :         return -1;
    2260                 :     
    2261                 : /* -------------------------------------------------------------------- */
    2262                 : /* Check that all bands have the same number of overviews and           */
    2263                 : /* that they have all the same size and block dimensions                */
    2264                 : /* -------------------------------------------------------------------- */
    2265               4 :     for( iBand = 0; iBand < nBandCount; iBand++ )
    2266                 :     {
    2267               2 :         GDALRasterBand *poBand = poDS->GetRasterBand( panBandMap[iBand] );
    2268               2 :         if (iBand == 0)
    2269                 :         {
    2270               2 :             poFirstBand = poBand;
    2271               2 :             nOverviewCount = poBand->GetOverviewCount();
    2272                 :         }
    2273               0 :         else if (nOverviewCount != poBand->GetOverviewCount())
    2274                 :         {
    2275                 :             CPLDebug( "GDAL", 
    2276                 :                       "GDALDataset::GetBestOverviewLevel() ... "
    2277               0 :                       "mismatched overview count, use std method." );
    2278               0 :             return -1;
    2279                 :         }
    2280                 :         else
    2281                 :         {
    2282               0 :             for(iOverview = 0; iOverview < nOverviewCount; iOverview++)
    2283                 :             {
    2284                 :                 GDALRasterBand* poOvrBand =
    2285               0 :                     poBand->GetOverview(iOverview);
    2286                 :                 GDALRasterBand* poOvrFirstBand =
    2287               0 :                     poFirstBand->GetOverview(iOverview);
    2288               0 :                 if ( poOvrBand == NULL || poOvrFirstBand == NULL)
    2289               0 :                     continue;
    2290                 : 
    2291               0 :                 if ( poOvrFirstBand->GetXSize() != poOvrBand->GetXSize() ||
    2292                 :                      poOvrFirstBand->GetYSize() != poOvrBand->GetYSize() )
    2293                 :                 {
    2294                 :                     CPLDebug( "GDAL", 
    2295                 :                               "GDALDataset::GetBestOverviewLevel() ... "
    2296               0 :                               "mismatched overview sizes, use std method." );
    2297               0 :                     return -1;
    2298                 :                 }
    2299               0 :                 int nBlockXSizeFirst=0, nBlockYSizeFirst=0;
    2300               0 :                 int nBlockXSizeCurrent=0, nBlockYSizeCurrent=0;
    2301               0 :                 poOvrFirstBand->GetBlockSize(&nBlockXSizeFirst, &nBlockYSizeFirst);
    2302               0 :                 poOvrBand->GetBlockSize(&nBlockXSizeCurrent, &nBlockYSizeCurrent);
    2303               0 :                 if (nBlockXSizeFirst != nBlockXSizeCurrent ||
    2304                 :                     nBlockYSizeFirst != nBlockYSizeCurrent)
    2305                 :                 {
    2306                 :                     CPLDebug( "GDAL", 
    2307                 :                           "GDALDataset::GetBestOverviewLevel() ... "
    2308               0 :                           "mismatched block sizes, use std method." );
    2309               0 :                     return -1;
    2310                 :                 }
    2311                 :             }
    2312                 :         }
    2313                 :     }
    2314                 :  
    2315                 :     return GDALBandGetBestOverviewLevel(poFirstBand,
    2316                 :                                         nXOff, nYOff, nXSize, nYSize,
    2317               2 :                                         nBufXSize, nBufYSize);
    2318                 : }
    2319                 : 
    2320                 : /************************************************************************/
    2321                 : /*                         BlockBasedRasterIO()                         */
    2322                 : /*                                                                      */
    2323                 : /*      This convenience function implements a dataset level            */
    2324                 : /*      RasterIO() interface based on calling down to fetch blocks,     */
    2325                 : /*      much like the GDALRasterBand::IRasterIO(), but it handles       */
    2326                 : /*      all bands at once, so that a format driver that handles a       */
    2327                 : /*      request for different bands of the same block efficiently       */
    2328                 : /*      (ie. without re-reading interleaved data) will efficiently.     */
    2329                 : /*                                                                      */
    2330                 : /*      This method is intended to be called by an overridden           */
    2331                 : /*      IRasterIO() method in the driver specific GDALDataset           */
    2332                 : /*      derived class.                                                  */
    2333                 : /*                                                                      */
    2334                 : /*      Default internal implementation of RasterIO() ... utilizes      */
    2335                 : /*      the Block access methods to satisfy the request.  This would    */
    2336                 : /*      normally only be overridden by formats with overviews.          */
    2337                 : /*                                                                      */
    2338                 : /*      To keep things relatively simple, this method does not          */
    2339                 : /*      currently take advantage of some special cases addressed in     */
    2340                 : /*      GDALRasterBand::IRasterIO(), so it is likely best to only       */
    2341                 : /*      call it when you know it will help.  That is in cases where     */
    2342                 : /*      data is at 1:1 to the buffer, and you know the driver is        */
    2343                 : /*      implementing interleaved IO efficiently on a block by block     */
    2344                 : /*      basis. Overviews will be used when possible.                    */
    2345                 : /************************************************************************/
    2346                 : 
    2347                 : CPLErr 
    2348            1513 : GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
    2349                 :                                  int nXOff, int nYOff, int nXSize, int nYSize,
    2350                 :                                  void * pData, int nBufXSize, int nBufYSize,
    2351                 :                                  GDALDataType eBufType,
    2352                 :                                  int nBandCount, int *panBandMap,
    2353                 :                                  int nPixelSpace, int nLineSpace,int nBandSpace)
    2354                 :     
    2355                 : {
    2356            1513 :     GByte      **papabySrcBlock = NULL;
    2357            1513 :     GDALRasterBlock *poBlock = NULL;
    2358            1513 :     GDALRasterBlock **papoBlocks = NULL;
    2359            1513 :     int         nLBlockX=-1, nLBlockY=-1, iBufYOff, iBufXOff, iSrcY, iBand;
    2360            1513 :     int         nBlockXSize=1, nBlockYSize=1;
    2361            1513 :     CPLErr      eErr = CE_None;
    2362            1513 :     GDALDataType eDataType = GDT_Byte;
    2363                 : 
    2364            1513 :     CPLAssert( NULL != pData );
    2365                 : 
    2366                 : /* -------------------------------------------------------------------- */
    2367                 : /*      Ensure that all bands share a common block size and data type.  */
    2368                 : /* -------------------------------------------------------------------- */
    2369                 : 
    2370            6234 :     for( iBand = 0; iBand < nBandCount; iBand++ )
    2371                 :     {
    2372            4721 :         GDALRasterBand *poBand = GetRasterBand( panBandMap[iBand] );
    2373                 :         int nThisBlockXSize, nThisBlockYSize;
    2374                 : 
    2375            4721 :         if( iBand == 0 )
    2376                 :         {
    2377            1513 :             poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
    2378            1513 :             eDataType = poBand->GetRasterDataType();
    2379                 :         }
    2380                 :         else
    2381                 :         {
    2382            3208 :             poBand->GetBlockSize( &nThisBlockXSize, &nThisBlockYSize );
    2383            3208 :             if( nThisBlockXSize != nBlockXSize 
    2384                 :                 || nThisBlockYSize != nBlockYSize )
    2385                 :             {
    2386                 :                 CPLDebug( "GDAL", 
    2387                 :                           "GDALDataset::BlockBasedRasterIO() ... "
    2388               0 :                           "mismatched block sizes, use std method." );
    2389                 :                 return GDALDataset::IRasterIO( eRWFlag, 
    2390                 :                                                nXOff, nYOff, nXSize, nYSize, 
    2391                 :                                                pData, nBufXSize, nBufYSize, 
    2392                 :                                                eBufType, 
    2393                 :                                                nBandCount, panBandMap,
    2394                 :                                                nPixelSpace, nLineSpace, 
    2395               0 :                                                nBandSpace );
    2396                 :             }
    2397                 : 
    2398            3208 :             if( eDataType != poBand->GetRasterDataType() 
    2399                 :                 && (nXSize != nBufXSize || nYSize != nBufYSize) )
    2400                 :             {
    2401                 :                 CPLDebug( "GDAL", 
    2402                 :                           "GDALDataset::BlockBasedRasterIO() ... "
    2403               0 :                           "mismatched band data types, use std method." );
    2404                 :                 return GDALDataset::IRasterIO( eRWFlag, 
    2405                 :                                                nXOff, nYOff, nXSize, nYSize, 
    2406                 :                                                pData, nBufXSize, nBufYSize, 
    2407                 :                                                eBufType, 
    2408                 :                                                nBandCount, panBandMap,
    2409                 :                                                nPixelSpace, nLineSpace, 
    2410               0 :                                                nBandSpace );
    2411                 :             }
    2412                 :         }
    2413                 :     }
    2414                 : 
    2415                 : /* ==================================================================== */
    2416                 : /*      In this special case at full resolution we step through in      */
    2417                 : /*      blocks, turning the request over to the per-band                */
    2418                 : /*      IRasterIO(), but ensuring that all bands of one block are       */
    2419                 : /*      called before proceeding to the next.                           */
    2420                 : /* ==================================================================== */
    2421            1513 :     if( nXSize == nBufXSize && nYSize == nBufYSize )    
    2422                 :     {
    2423                 :         int nChunkYSize, nChunkXSize, nChunkXOff, nChunkYOff;
    2424                 : 
    2425           11919 :         for( iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff += nChunkYSize )
    2426                 :         {
    2427           10408 :             nChunkYSize = nBlockYSize;
    2428           10408 :             nChunkYOff = iBufYOff + nYOff;
    2429           10408 :             nChunkYSize = nBlockYSize - (nChunkYOff % nBlockYSize);
    2430           10408 :             if( nChunkYSize == 0 )
    2431               0 :                 nChunkYSize = nBlockYSize;
    2432           10408 :             if( nChunkYOff + nChunkYSize > nYOff + nYSize )
    2433             642 :                 nChunkYSize = (nYOff + nYSize) - nChunkYOff;
    2434                 : 
    2435           20925 :             for( iBufXOff = 0; iBufXOff < nBufXSize; iBufXOff += nChunkXSize )
    2436                 :             {
    2437           10517 :                 nChunkXSize = nBlockXSize;
    2438           10517 :                 nChunkXOff = iBufXOff + nXOff;
    2439           10517 :                 nChunkXSize = nBlockXSize - (nChunkXOff % nBlockXSize);
    2440           10517 :                 if( nChunkXSize == 0 )
    2441               0 :                     nChunkXSize = nBlockXSize;
    2442           10517 :                 if( nChunkXOff + nChunkXSize > nXOff + nXSize )
    2443             630 :                     nChunkXSize = (nXOff + nXSize) - nChunkXOff;
    2444                 : 
    2445                 :                 GByte *pabyChunkData;
    2446                 : 
    2447                 :                 pabyChunkData = ((GByte *) pData) 
    2448                 :                     + iBufXOff * nPixelSpace 
    2449           10517 :                     + iBufYOff * nLineSpace;
    2450                 : 
    2451           29120 :                 for( iBand = 0; iBand < nBandCount; iBand++ )
    2452                 :                 {
    2453           18603 :                     GDALRasterBand *poBand = GetRasterBand(panBandMap[iBand]);
    2454                 :                     
    2455                 :                     eErr = 
    2456                 :                         poBand->GDALRasterBand::IRasterIO( 
    2457                 :                             eRWFlag, nChunkXOff, nChunkYOff, 
    2458                 :                             nChunkXSize, nChunkYSize, 
    2459                 :                             pabyChunkData + iBand * nBandSpace, 
    2460                 :                             nChunkXSize, nChunkYSize, eBufType, 
    2461           18603 :                             nPixelSpace, nLineSpace );
    2462           18603 :                     if( eErr != CE_None )
    2463               0 :                         return eErr;
    2464                 :                 }
    2465                 :             }
    2466                 :         }
    2467                 : 
    2468            1511 :         return CE_None;
    2469                 :     }
    2470                 :     
    2471                 :     /* Below code is not compatible with that case. It would need a complete */
    2472                 :     /* separate code like done in GDALRasterBand::IRasterIO. */
    2473               2 :     if (eRWFlag == GF_Write && (nBufXSize < nXSize || nBufYSize < nYSize))
    2474                 :     {
    2475                 :         return GDALDataset::IRasterIO( eRWFlag, 
    2476                 :                                        nXOff, nYOff, nXSize, nYSize, 
    2477                 :                                        pData, nBufXSize, nBufYSize, 
    2478                 :                                        eBufType, 
    2479                 :                                        nBandCount, panBandMap,
    2480                 :                                        nPixelSpace, nLineSpace, 
    2481               0 :                                        nBandSpace );
    2482                 :     }
    2483                 : 
    2484                 : /* ==================================================================== */
    2485                 : /*      Loop reading required source blocks to satisfy output           */
    2486                 : /*      request.  This is the most general implementation.              */
    2487                 : /* ==================================================================== */
    2488                 : 
    2489               2 :     int         nBandDataSize = GDALGetDataTypeSize( eDataType ) / 8;
    2490                 : 
    2491               2 :     papabySrcBlock = (GByte **) CPLCalloc(sizeof(GByte*),nBandCount);
    2492               2 :     papoBlocks = (GDALRasterBlock **) CPLCalloc(sizeof(void*),nBandCount);
    2493                 :     
    2494                 : /* -------------------------------------------------------------------- */
    2495                 : /*      Select an overview level if appropriate.                        */
    2496                 : /* -------------------------------------------------------------------- */
    2497                 :     int nOverviewLevel = GDALDatasetGetBestOverviewLevel (this,
    2498                 :                                                nXOff, nYOff, nXSize, nYSize,
    2499                 :                                                nBufXSize, nBufYSize,
    2500               2 :                                                nBandCount, panBandMap);
    2501               2 :     if (nOverviewLevel >= 0)
    2502                 :     {
    2503               2 :         GetRasterBand(panBandMap[0])->GetOverview(nOverviewLevel)->
    2504               4 :                                 GetBlockSize( &nBlockXSize, &nBlockYSize );
    2505                 :     }
    2506                 : 
    2507                 : /* -------------------------------------------------------------------- */
    2508                 : /*      Compute stepping increment.                                     */
    2509                 : /* -------------------------------------------------------------------- */
    2510                 :     double      dfSrcX, dfSrcY, dfSrcXInc, dfSrcYInc;
    2511                 :     
    2512               2 :     dfSrcXInc = nXSize / (double) nBufXSize;
    2513               2 :     dfSrcYInc = nYSize / (double) nBufYSize;
    2514                 : 
    2515                 : /* -------------------------------------------------------------------- */
    2516                 : /*      Loop over buffer computing source locations.                    */
    2517                 : /* -------------------------------------------------------------------- */
    2518              12 :     for( iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff++ )
    2519                 :     {
    2520                 :         int     iBufOffset, iSrcOffset;
    2521                 :         
    2522              10 :         dfSrcY = (iBufYOff+0.5) * dfSrcYInc + nYOff;
    2523              10 :         iSrcY = (int) dfSrcY;
    2524                 : 
    2525              10 :         iBufOffset = iBufYOff * nLineSpace;
    2526                 :         
    2527              60 :         for( iBufXOff = 0; iBufXOff < nBufXSize; iBufXOff++ )
    2528                 :         {
    2529                 :             int iSrcX;
    2530                 : 
    2531              50 :             dfSrcX = (iBufXOff+0.5) * dfSrcXInc + nXOff;
    2532                 :             
    2533              50 :             iSrcX = (int) dfSrcX;
    2534                 : 
    2535                 : /* -------------------------------------------------------------------- */
    2536                 : /*      Ensure we have the appropriate block loaded.                    */
    2537                 : /* -------------------------------------------------------------------- */
    2538              50 :             if( iSrcX < nLBlockX * nBlockXSize
    2539                 :                 || iSrcX >= (nLBlockX+1) * nBlockXSize
    2540                 :                 || iSrcY < nLBlockY * nBlockYSize
    2541                 :                 || iSrcY >= (nLBlockY+1) * nBlockYSize )
    2542                 :             {
    2543               2 :                 nLBlockX = iSrcX / nBlockXSize;
    2544               2 :                 nLBlockY = iSrcY / nBlockYSize;
    2545                 : 
    2546                 :                 int bJustInitialize = 
    2547                 :                     eRWFlag == GF_Write
    2548                 :                     && nYOff <= nLBlockY * nBlockYSize
    2549                 :                     && nYOff + nYSize >= (nLBlockY+1) * nBlockYSize
    2550                 :                     && nXOff <= nLBlockX * nBlockXSize
    2551               2 :                     && nXOff + nXSize >= (nLBlockX+1) * nBlockXSize;
    2552                 : 
    2553               4 :                 for( iBand = 0; iBand < nBandCount; iBand++ )
    2554                 :                 {
    2555               2 :                     GDALRasterBand *poBand = GetRasterBand( panBandMap[iBand]);
    2556               2 :                     if (nOverviewLevel >= 0)
    2557               2 :                         poBand = poBand->GetOverview(nOverviewLevel);
    2558                 :                     poBlock = poBand->GetLockedBlockRef( nLBlockX, nLBlockY, 
    2559               2 :                                                          bJustInitialize );
    2560               2 :                     if( poBlock == NULL )
    2561                 :                     {
    2562               0 :                         eErr = CE_Failure;
    2563               0 :                         goto CleanupAndReturn;
    2564                 :                     }
    2565                 : 
    2566               2 :                     if( eRWFlag == GF_Write )
    2567               0 :                         poBlock->MarkDirty();
    2568                 : 
    2569               2 :                     if( papoBlocks[iBand] != NULL )
    2570               0 :                         papoBlocks[iBand]->DropLock();
    2571                 :                 
    2572               2 :                     papoBlocks[iBand] = poBlock;
    2573                 : 
    2574               2 :                     papabySrcBlock[iBand] = (GByte *) poBlock->GetDataRef();
    2575               2 :                     if( papabySrcBlock[iBand] == NULL )
    2576                 :                     {
    2577               0 :                         eErr = CE_Failure; 
    2578               0 :                         goto CleanupAndReturn;
    2579                 :                     }
    2580                 :                 }
    2581                 :             }
    2582                 : 
    2583                 : /* -------------------------------------------------------------------- */
    2584                 : /*      Copy over this pixel of data.                                   */
    2585                 : /* -------------------------------------------------------------------- */
    2586                 :             iSrcOffset = (iSrcX - nLBlockX*nBlockXSize
    2587              50 :                 + (iSrcY - nLBlockY*nBlockYSize) * nBlockXSize)*nBandDataSize;
    2588                 : 
    2589             100 :             for( iBand = 0; iBand < nBandCount; iBand++ )
    2590                 :             {
    2591              50 :                 GByte *pabySrcBlock = papabySrcBlock[iBand];
    2592              50 :                 int iBandBufOffset = iBufOffset + iBand * nBandSpace;
    2593                 :                 
    2594              50 :                 if( eDataType == eBufType )
    2595                 :                 {
    2596              50 :                     if( eRWFlag == GF_Read )
    2597                 :                         memcpy( ((GByte *) pData) + iBandBufOffset,
    2598              50 :                                 pabySrcBlock + iSrcOffset, nBandDataSize );
    2599                 :                 else
    2600                 :                     memcpy( pabySrcBlock + iSrcOffset, 
    2601               0 :                             ((GByte *)pData) + iBandBufOffset, nBandDataSize );
    2602                 :                 }
    2603                 :                 else
    2604                 :                 {
    2605                 :                     /* type to type conversion ... ouch, this is expensive way
    2606                 :                        of handling single words */
    2607                 :                     
    2608               0 :                     if( eRWFlag == GF_Read )
    2609                 :                         GDALCopyWords( pabySrcBlock + iSrcOffset, eDataType, 0,
    2610                 :                                        ((GByte *) pData) + iBandBufOffset, 
    2611               0 :                                        eBufType, 0, 1 );
    2612                 :                     else
    2613                 :                         GDALCopyWords( ((GByte *) pData) + iBandBufOffset, 
    2614                 :                                        eBufType, 0,
    2615                 :                                        pabySrcBlock + iSrcOffset, eDataType, 0,
    2616               0 :                                        1 );
    2617                 :                 }
    2618                 :             }
    2619                 : 
    2620              50 :             iBufOffset += nPixelSpace;
    2621                 :         }
    2622                 :     }
    2623                 : 
    2624                 : /* -------------------------------------------------------------------- */
    2625                 : /*      CleanupAndReturn.                                               */
    2626                 : /* -------------------------------------------------------------------- */
    2627                 :   CleanupAndReturn:
    2628               2 :     CPLFree( papabySrcBlock );
    2629               2 :     if( papoBlocks != NULL )
    2630                 :     {
    2631               4 :         for( iBand = 0; iBand < nBandCount; iBand++ )
    2632                 :         {
    2633               2 :             if( papoBlocks[iBand] != NULL )
    2634               2 :                 papoBlocks[iBand]->DropLock();
    2635                 :         }
    2636               2 :         CPLFree( papoBlocks );
    2637                 :     }
    2638                 : 
    2639               2 :     return( CE_None );
    2640                 : }
    2641                 : 
    2642                 : /************************************************************************/
    2643                 : /*                  GDALCopyWholeRasterGetSwathSize()                   */
    2644                 : /************************************************************************/
    2645                 : 
    2646             514 : static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
    2647                 :                                             GDALRasterBand *poDstPrototypeBand,
    2648                 :                                             int nBandCount,
    2649                 :                                             int bDstIsCompressed, int bInterleave,
    2650                 :                                             int* pnSwathCols, int *pnSwathLines)
    2651                 : {
    2652             514 :     GDALDataType eDT = poDstPrototypeBand->GetRasterDataType();
    2653                 :     int nSrcBlockXSize, nSrcBlockYSize;
    2654                 :     int nBlockXSize, nBlockYSize;
    2655                 : 
    2656             514 :     int nXSize = poSrcPrototypeBand->GetXSize();
    2657             514 :     int nYSize = poSrcPrototypeBand->GetYSize();
    2658                 : 
    2659             514 :     poSrcPrototypeBand->GetBlockSize( &nSrcBlockXSize, &nSrcBlockYSize );
    2660             514 :     poDstPrototypeBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
    2661                 : 
    2662             514 :     int nMaxBlockXSize = MAX(nBlockXSize, nSrcBlockXSize);
    2663             514 :     int nMaxBlockYSize = MAX(nBlockYSize, nSrcBlockYSize);
    2664                 :     
    2665                 : /* -------------------------------------------------------------------- */
    2666                 : /*      What will our swath size be?                                    */
    2667                 : /* -------------------------------------------------------------------- */
    2668                 :     /* When writing interleaved data in a compressed format, we want to be sure */
    2669                 :     /* that each block will only be written once, so the swath size must not be */
    2670                 :     /* greater than the block cache. */
    2671                 :     /* So as the default cache size is 40 MB, 10 MB is a safe value */
    2672             514 :     int nTargetSwathSize = atoi(CPLGetConfigOption("GDAL_SWATH_SIZE", "10000000"));
    2673             514 :     if (nTargetSwathSize < 1000000)
    2674               0 :         nTargetSwathSize = 1000000;
    2675                 : 
    2676                 :     /* But let's check that  */
    2677             514 :     if (bDstIsCompressed && bInterleave && nTargetSwathSize > GDALGetCacheMax64())
    2678                 :     {
    2679                 :         CPLError(CE_Warning, CPLE_AppDefined,
    2680                 :                  "When translating into a compressed interleave format, the block cache size (" CPL_FRMT_GIB ") "
    2681               0 :                  "should be at least the size of the swath (%d)", GDALGetCacheMax64(), nTargetSwathSize);
    2682                 :     }
    2683                 : 
    2684             514 :     int nPixelSize = (GDALGetDataTypeSize(eDT) / 8);
    2685             514 :     if( bInterleave)
    2686             115 :         nPixelSize *= nBandCount;
    2687                 : 
    2688                 :     // aim for one row of blocks.  Do not settle for less.
    2689             514 :     int nSwathCols  = nXSize;
    2690             514 :     int nSwathLines = nBlockYSize;
    2691                 : 
    2692                 : #define IS_MULTIPLE_OF(x,y) ((y)%(x) == 0)
    2693                 : #define ROUND_TO(x,y) (((x)/(y))*(y))
    2694                 : 
    2695                 :     /* if both input and output datasets are tiled, that the tile dimensions */
    2696                 :     /* are "compatible", try to stick  to a swath dimension that is a multiple */
    2697                 :     /* of input and output block dimensions */
    2698             514 :     if (nBlockXSize != nXSize && nSrcBlockXSize != nXSize &&
    2699                 :         IS_MULTIPLE_OF(nBlockXSize, nMaxBlockXSize) &&
    2700                 :         IS_MULTIPLE_OF(nSrcBlockXSize, nMaxBlockXSize) &&
    2701                 :         IS_MULTIPLE_OF(nBlockYSize, nMaxBlockYSize) &&
    2702                 :         IS_MULTIPLE_OF(nSrcBlockYSize, nMaxBlockYSize))
    2703                 :     {
    2704              19 :         if (((GIntBig)nMaxBlockXSize) * nMaxBlockYSize * nPixelSize <=
    2705                 :                                                     (GIntBig)nTargetSwathSize)
    2706                 :         {
    2707              19 :             nSwathCols = nTargetSwathSize / (nMaxBlockYSize * nPixelSize);
    2708              19 :             nSwathCols = ROUND_TO(nSwathCols, nMaxBlockXSize);
    2709              19 :             if (nSwathCols == 0)
    2710               0 :                 nSwathCols = nMaxBlockXSize;
    2711              19 :             if (nSwathCols > nXSize)
    2712              19 :                 nSwathCols = nXSize;
    2713              19 :             nSwathLines = nMaxBlockYSize;
    2714                 : 
    2715              19 :             if (((GIntBig)nSwathCols) * nSwathLines * nPixelSize >
    2716                 :                                                     (GIntBig)nTargetSwathSize)
    2717                 :             {
    2718               0 :                 nSwathCols  = nXSize;
    2719               0 :                 nSwathLines = nBlockYSize;
    2720                 :             }
    2721                 :         }
    2722                 :     }
    2723                 : 
    2724             514 :     int nMemoryPerCol = nSwathCols * nPixelSize;
    2725                 : 
    2726                 :     /* Do the computation on a big int since for example when translating */
    2727                 :     /* the JPL WMS layer, we overflow 32 bits*/
    2728             514 :     GIntBig nSwathBufSize = (GIntBig)nMemoryPerCol * nSwathLines;
    2729             514 :     if (nSwathBufSize > (GIntBig)nTargetSwathSize)
    2730                 :     {
    2731               0 :         nSwathLines = nTargetSwathSize / nMemoryPerCol;
    2732               0 :         if (nSwathLines == 0)
    2733               0 :             nSwathLines = 1;
    2734                 : 
    2735                 :         CPLDebug( "GDAL",
    2736                 :               "GDALCopyWholeRasterGetSwathSize(): adjusting to %d line swath "
    2737                 :               "since requirement (%d * %d bytes) exceed target swath size (%d bytes) ",
    2738               0 :               nSwathLines, nBlockYSize, nMemoryPerCol, nTargetSwathSize);
    2739                 :     }
    2740                 :     // If we are processing single scans, try to handle several at once.
    2741                 :     // If we are handling swaths already, only grow the swath if a row
    2742                 :     // of blocks is substantially less than our target buffer size.
    2743             514 :     else if( nSwathLines == 1
    2744                 :         || nMemoryPerCol * nSwathLines < nTargetSwathSize / 10 )
    2745                 :     {
    2746             511 :         nSwathLines = MIN(nYSize,MAX(1,nTargetSwathSize/nMemoryPerCol));
    2747                 : 
    2748                 :         /* If possible try to align to source and target block height */
    2749             511 :         if ((nSwathLines % nMaxBlockYSize) != 0 && nSwathLines > nMaxBlockYSize &&
    2750                 :             IS_MULTIPLE_OF(nBlockYSize, nMaxBlockYSize) &&
    2751                 :             IS_MULTIPLE_OF(nSrcBlockYSize, nMaxBlockYSize))
    2752              22 :             nSwathLines = ROUND_TO(nSwathLines, nMaxBlockYSize);
    2753                 :     }
    2754                 : 
    2755                 : 
    2756             514 :     if (bDstIsCompressed)
    2757                 :     {
    2758              23 :         if (nSwathLines < nBlockYSize)
    2759                 :         {
    2760               0 :             nSwathLines = nBlockYSize;
    2761                 : 
    2762                 :             /* Number of pixels that can be read/write simultaneously */
    2763               0 :             nSwathCols = nTargetSwathSize / (nSwathLines * nPixelSize);
    2764               0 :             nSwathCols = ROUND_TO(nSwathCols, nBlockXSize);
    2765               0 :             if (nSwathCols == 0)
    2766               0 :                 nSwathCols = nBlockXSize;
    2767               0 :             if (nSwathCols > nXSize)
    2768               0 :                 nSwathCols = nXSize;
    2769                 : 
    2770                 :             CPLDebug( "GDAL",
    2771                 :               "GDALCopyWholeRasterGetSwathSize(): because of compression and too high block,\n"
    2772               0 :               "use partial width at one time");
    2773                 :         }
    2774              23 :         else if ((nSwathLines % nBlockYSize) != 0)
    2775                 :         {
    2776                 :             /* Round on a multiple of nBlockYSize */
    2777               4 :             nSwathLines = ROUND_TO(nSwathLines, nBlockYSize);
    2778                 :             CPLDebug( "GDAL",
    2779                 :               "GDALCopyWholeRasterGetSwathSize(): because of compression, \n"
    2780               4 :               "round nSwathLines to block height : %d", nSwathLines);
    2781                 :         }
    2782                 :     }
    2783                 : 
    2784             514 :     *pnSwathCols = nSwathCols;
    2785             514 :     *pnSwathLines = nSwathLines;
    2786             514 : }
    2787                 : 
    2788                 : /************************************************************************/
    2789                 : /*                     GDALDatasetCopyWholeRaster()                     */
    2790                 : /************************************************************************/
    2791                 : 
    2792                 : /**
    2793                 :  * \brief Copy all dataset raster data.
    2794                 :  *
    2795                 :  * This function copies the complete raster contents of one dataset to 
    2796                 :  * another similarly configured dataset.  The source and destination 
    2797                 :  * dataset must have the same number of bands, and the same width
    2798                 :  * and height.  The bands do not have to have the same data type. 
    2799                 :  *
    2800                 :  * This function is primarily intended to support implementation of 
    2801                 :  * driver specific CreateCopy() functions.  It implements efficient copying,
    2802                 :  * in particular "chunking" the copy in substantial blocks and, if appropriate,
    2803                 :  * performing the transfer in a pixel interleaved fashion.
    2804                 :  *
    2805                 :  * Currently the only papszOptions value supported are : "INTERLEAVE=PIXEL"
    2806                 :  * to force pixel interleaved operation and "COMPRESSED=YES" to force alignment
    2807                 :  * on target dataset block sizes to achieve best compression.  More options may be supported in
    2808                 :  * the future.  
    2809                 :  *
    2810                 :  * @param hSrcDS the source dataset
    2811                 :  * @param hDstDS the destination dataset
    2812                 :  * @param papszOptions transfer hints in "StringList" Name=Value format.
    2813                 :  * @param pfnProgress progress reporting function.
    2814                 :  * @param pProgressData callback data for progress function.
    2815                 :  *
    2816                 :  * @return CE_None on success, or CE_Failure on failure. 
    2817                 :  */
    2818                 : 
    2819             510 : CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
    2820                 :     GDALDatasetH hSrcDS, GDALDatasetH hDstDS, char **papszOptions, 
    2821                 :     GDALProgressFunc pfnProgress, void *pProgressData )
    2822                 : 
    2823                 : {
    2824             510 :     VALIDATE_POINTER1( hSrcDS, "GDALDatasetCopyWholeRaster", CE_Failure );
    2825             510 :     VALIDATE_POINTER1( hDstDS, "GDALDatasetCopyWholeRaster", CE_Failure );
    2826                 : 
    2827             510 :     GDALDataset *poSrcDS = (GDALDataset *) hSrcDS;
    2828             510 :     GDALDataset *poDstDS = (GDALDataset *) hDstDS;
    2829             510 :     CPLErr eErr = CE_None;
    2830                 : 
    2831             510 :     if( pfnProgress == NULL )
    2832               0 :         pfnProgress = GDALDummyProgress;
    2833                 : 
    2834                 : /* -------------------------------------------------------------------- */
    2835                 : /*      Confirm the datasets match in size and band counts.             */
    2836                 : /* -------------------------------------------------------------------- */
    2837             510 :     int nXSize = poDstDS->GetRasterXSize(), 
    2838             510 :         nYSize = poDstDS->GetRasterYSize(),
    2839             510 :         nBandCount = poDstDS->GetRasterCount();
    2840                 : 
    2841             510 :     if( poSrcDS->GetRasterXSize() != nXSize 
    2842                 :         || poSrcDS->GetRasterYSize() != nYSize
    2843                 :         || poSrcDS->GetRasterCount() != nBandCount )
    2844                 :     {
    2845                 :         CPLError( CE_Failure, CPLE_AppDefined,
    2846                 :                   "Input and output dataset sizes or band counts do not\n"
    2847               2 :                   "match in GDALDatasetCopyWholeRaster()" );
    2848               2 :         return CE_Failure;
    2849                 :     }
    2850                 : 
    2851                 : /* -------------------------------------------------------------------- */
    2852                 : /*      Report preliminary (0) progress.                                */
    2853                 : /* -------------------------------------------------------------------- */
    2854             508 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
    2855                 :     {
    2856                 :         CPLError( CE_Failure, CPLE_UserInterrupt, 
    2857               0 :                   "User terminated CreateCopy()" );
    2858               0 :         return CE_Failure;
    2859                 :     }
    2860                 : 
    2861                 : /* -------------------------------------------------------------------- */
    2862                 : /*      Get our prototype band, and assume the others are similarly     */
    2863                 : /*      configured.                                                     */
    2864                 : /* -------------------------------------------------------------------- */
    2865             508 :     if( nBandCount == 0 )
    2866               0 :         return CE_None;
    2867                 : 
    2868             508 :     GDALRasterBand *poSrcPrototypeBand = poSrcDS->GetRasterBand(1);
    2869             508 :     GDALRasterBand *poDstPrototypeBand = poDstDS->GetRasterBand(1);
    2870             508 :     GDALDataType eDT = poDstPrototypeBand->GetRasterDataType();
    2871                 : 
    2872                 : /* -------------------------------------------------------------------- */
    2873                 : /*      Do we want to try and do the operation in a pixel               */
    2874                 : /*      interleaved fashion?                                            */
    2875                 : /* -------------------------------------------------------------------- */
    2876             508 :     int bInterleave = FALSE;
    2877             508 :     const char *pszInterleave = NULL;
    2878                 :     
    2879             508 :     pszInterleave = poSrcDS->GetMetadataItem( "INTERLEAVE", "IMAGE_STRUCTURE");
    2880             508 :     if( pszInterleave != NULL 
    2881                 :         && (EQUAL(pszInterleave,"PIXEL") || EQUAL(pszInterleave,"LINE")) )
    2882              87 :         bInterleave = TRUE;
    2883                 : 
    2884             508 :     pszInterleave = poDstDS->GetMetadataItem( "INTERLEAVE", "IMAGE_STRUCTURE");
    2885             508 :     if( pszInterleave != NULL 
    2886                 :         && (EQUAL(pszInterleave,"PIXEL") || EQUAL(pszInterleave,"LINE")) )
    2887              52 :         bInterleave = TRUE;
    2888                 : 
    2889             508 :     pszInterleave = CSLFetchNameValue( papszOptions, "INTERLEAVE" );
    2890             508 :     if( pszInterleave != NULL 
    2891                 :         && (EQUAL(pszInterleave,"PIXEL") || EQUAL(pszInterleave,"LINE")) )
    2892               0 :         bInterleave = TRUE;
    2893                 : 
    2894                 :     /* If the destination is compressed, we must try to write blocks just once, to save */
    2895                 :     /* disk space (GTiff case for example), and to avoid data loss (JPEG compression for example) */
    2896             508 :     int bDstIsCompressed = FALSE;
    2897             508 :     const char* pszDstCompressed= CSLFetchNameValue( papszOptions, "COMPRESSED" );
    2898             508 :     if (pszDstCompressed != NULL && CSLTestBoolean(pszDstCompressed))
    2899              19 :         bDstIsCompressed = TRUE;
    2900                 : 
    2901                 : /* -------------------------------------------------------------------- */
    2902                 : /*      What will our swath size be?                                    */
    2903                 : /* -------------------------------------------------------------------- */
    2904                 : 
    2905                 :     int nSwathCols, nSwathLines;
    2906                 :     GDALCopyWholeRasterGetSwathSize(poSrcPrototypeBand,
    2907                 :                                     poDstPrototypeBand,
    2908                 :                                     nBandCount,
    2909                 :                                     bDstIsCompressed, bInterleave,
    2910             508 :                                     &nSwathCols, &nSwathLines);
    2911                 : 
    2912             508 :     int nPixelSize = (GDALGetDataTypeSize(eDT) / 8);
    2913             508 :     if( bInterleave)
    2914             115 :         nPixelSize *= nBandCount;
    2915                 : 
    2916             508 :     void *pSwathBuf = VSIMalloc3(nSwathCols, nSwathLines, nPixelSize );
    2917             508 :     if( pSwathBuf == NULL )
    2918                 :     {
    2919                 :         CPLError( CE_Failure, CPLE_OutOfMemory,
    2920                 :                 "Failed to allocate %d*%d*%d byte swath buffer in\n"
    2921                 :                 "GDALDatasetCopyWholeRaster()",
    2922               0 :                 nSwathCols, nSwathLines, nPixelSize );
    2923               0 :         return CE_Failure;
    2924                 :     }
    2925                 : 
    2926                 :     CPLDebug( "GDAL", 
    2927                 :             "GDALDatasetCopyWholeRaster(): %d*%d swaths, bInterleave=%d", 
    2928             508 :             nSwathCols, nSwathLines, bInterleave );
    2929                 : 
    2930                 : /* ==================================================================== */
    2931                 : /*      Band oriented (uninterleaved) case.                             */
    2932                 : /* ==================================================================== */
    2933             508 :     if( !bInterleave )
    2934                 :     {
    2935                 :         int iBand, iX, iY;
    2936                 : 
    2937             811 :         for( iBand = 0; iBand < nBandCount && eErr == CE_None; iBand++ )
    2938                 :         {
    2939             418 :             int nBand = iBand+1;
    2940                 : 
    2941             854 :             for( iY = 0; iY < nYSize && eErr == CE_None; iY += nSwathLines )
    2942                 :             {
    2943             436 :                 int nThisLines = nSwathLines;
    2944                 : 
    2945             436 :                 if( iY + nThisLines > nYSize )
    2946              15 :                     nThisLines = nYSize - iY;
    2947                 : 
    2948             872 :                 for( iX = 0; iX < nXSize && eErr == CE_None; iX += nSwathCols )
    2949                 :                 {
    2950             436 :                     int nThisCols = nSwathCols;
    2951                 : 
    2952             436 :                     if( iX + nThisCols > nXSize )
    2953               0 :                         nThisCols = nXSize - iX;
    2954                 : 
    2955                 :                     eErr = poSrcDS->RasterIO( GF_Read, 
    2956                 :                                             iX, iY, nThisCols, nThisLines,
    2957                 :                                             pSwathBuf, nThisCols, nThisLines, 
    2958                 :                                             eDT, 1, &nBand, 
    2959             436 :                                             0, 0, 0 );
    2960                 : 
    2961             436 :                     if( eErr == CE_None )
    2962                 :                         eErr = poDstDS->RasterIO( GF_Write, 
    2963                 :                                                 iX, iY, nThisCols, nThisLines,
    2964                 :                                                 pSwathBuf, nThisCols, nThisLines, 
    2965                 :                                                 eDT, 1, &nBand,
    2966             434 :                                                 0, 0, 0 );
    2967                 : 
    2968             436 :                     if( eErr == CE_None 
    2969                 :                         && !pfnProgress( 
    2970                 :                             iBand / (float)nBandCount
    2971                 :                             + (iY+nThisLines) / (float) (nYSize*nBandCount),
    2972                 :                             NULL, pProgressData ) )
    2973                 :                     {
    2974              12 :                         eErr = CE_Failure;
    2975                 :                         CPLError( CE_Failure, CPLE_UserInterrupt, 
    2976              12 :                                 "User terminated CreateCopy()" );
    2977                 :                     }
    2978                 :                 }
    2979                 :             }
    2980                 :         }
    2981                 :     }
    2982                 : 
    2983                 : /* ==================================================================== */
    2984                 : /*      Pixel interleaved case.                                         */
    2985                 : /* ==================================================================== */
    2986                 :     else /* if( bInterleave ) */
    2987                 :     {
    2988                 :         int iY, iX;
    2989                 : 
    2990             246 :         for( iY = 0; iY < nYSize && eErr == CE_None; iY += nSwathLines )
    2991                 :         {
    2992             131 :             int nThisLines = nSwathLines;
    2993                 : 
    2994             131 :             if( iY + nThisLines > nYSize )
    2995              10 :                 nThisLines = nYSize - iY;
    2996                 : 
    2997             262 :             for( iX = 0; iX < nXSize && eErr == CE_None; iX += nSwathCols )
    2998                 :             {
    2999             131 :                 int nThisCols = nSwathCols;
    3000                 : 
    3001             131 :                 if( iX + nThisCols > nXSize )
    3002               0 :                     nThisCols = nXSize - iX;
    3003                 : 
    3004                 :                 eErr = poSrcDS->RasterIO( GF_Read, 
    3005                 :                                         iX, iY, nThisCols, nThisLines,
    3006                 :                                         pSwathBuf, nThisCols, nThisLines, 
    3007                 :                                         eDT, nBandCount, NULL, 
    3008             131 :                                         0, 0, 0 );
    3009                 : 
    3010             131 :                 if( eErr == CE_None )
    3011                 :                     eErr = poDstDS->RasterIO( GF_Write, 
    3012                 :                                             iX, iY, nThisCols, nThisLines,
    3013                 :                                             pSwathBuf, nThisCols, nThisLines, 
    3014                 :                                             eDT, nBandCount, NULL, 
    3015             131 :                                             0, 0, 0 );
    3016                 : 
    3017             131 :                 if( eErr == CE_None 
    3018                 :                     && !pfnProgress( (iY+nThisLines) / (float) nYSize,
    3019                 :                                     NULL, pProgressData ) )
    3020                 :                 {
    3021               4 :                     eErr = CE_Failure;
    3022                 :                     CPLError( CE_Failure, CPLE_UserInterrupt, 
    3023               4 :                             "User terminated CreateCopy()" );
    3024                 :                 }
    3025                 :             }
    3026                 :         }
    3027                 :     }
    3028                 : 
    3029                 : /* -------------------------------------------------------------------- */
    3030                 : /*      Cleanup                                                         */
    3031                 : /* -------------------------------------------------------------------- */
    3032             508 :     CPLFree( pSwathBuf );
    3033                 : 
    3034             508 :     return eErr;
    3035                 : }
    3036                 : 
    3037                 : 
    3038                 : /************************************************************************/
    3039                 : /*                     GDALRasterBandCopyWholeRaster()                  */
    3040                 : /************************************************************************/
    3041                 : 
    3042                 : /**
    3043                 :  * \brief Copy all raster band raster data.
    3044                 :  *
    3045                 :  * This function copies the complete raster contents of one band to
    3046                 :  * another similarly configured band.  The source and destination
    3047                 :  * bands must have the same width and height.  The bands do not have
    3048                 :  * to have the same data type.
    3049                 :  *
    3050                 :  * It implements efficient copying, in particular "chunking" the copy in
    3051                 :  * substantial blocks.
    3052                 :  *
    3053                 :  * Currently the only papszOptions value supported is : "COMPRESSED=YES" to
    3054                 :  * force alignment on target dataset block sizes to achieve best compression.
    3055                 :  * More options may be supported in the future.
    3056                 :  *
    3057                 :  * @param hSrcBand the source band
    3058                 :  * @param hDstBand the destination band
    3059                 :  * @param papszOptions transfer hints in "StringList" Name=Value format.
    3060                 :  * @param pfnProgress progress reporting function.
    3061                 :  * @param pProgressData callback data for progress function.
    3062                 :  *
    3063                 :  * @return CE_None on success, or CE_Failure on failure.
    3064                 :  */
    3065                 : 
    3066               6 : CPLErr CPL_STDCALL GDALRasterBandCopyWholeRaster(
    3067                 :     GDALRasterBandH hSrcBand, GDALRasterBandH hDstBand, char **papszOptions,
    3068                 :     GDALProgressFunc pfnProgress, void *pProgressData )
    3069                 : 
    3070                 : {
    3071               6 :     VALIDATE_POINTER1( hSrcBand, "GDALRasterBandCopyWholeRaster", CE_Failure );
    3072               6 :     VALIDATE_POINTER1( hDstBand, "GDALRasterBandCopyWholeRaster", CE_Failure );
    3073                 : 
    3074               6 :     GDALRasterBand *poSrcBand = (GDALRasterBand *) hSrcBand;
    3075               6 :     GDALRasterBand *poDstBand = (GDALRasterBand *) hDstBand;
    3076               6 :     CPLErr eErr = CE_None;
    3077                 : 
    3078               6 :     if( pfnProgress == NULL )
    3079               0 :         pfnProgress = GDALDummyProgress;
    3080                 : 
    3081                 : /* -------------------------------------------------------------------- */
    3082                 : /*      Confirm the datasets match in size and band counts.             */
    3083                 : /* -------------------------------------------------------------------- */
    3084               6 :     int nXSize = poSrcBand->GetXSize(),
    3085               6 :         nYSize = poSrcBand->GetYSize();
    3086                 : 
    3087               6 :     if( poDstBand->GetXSize() != nXSize
    3088                 :         || poDstBand->GetYSize() != nYSize )
    3089                 :     {
    3090                 :         CPLError( CE_Failure, CPLE_AppDefined,
    3091                 :                   "Input and output band sizes do not\n"
    3092               0 :                   "match in GDALRasterBandCopyWholeRaster()" );
    3093               0 :         return CE_Failure;
    3094                 :     }
    3095                 : 
    3096                 : /* -------------------------------------------------------------------- */
    3097                 : /*      Report preliminary (0) progress.                                */
    3098                 : /* -------------------------------------------------------------------- */
    3099               6 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
    3100                 :     {
    3101                 :         CPLError( CE_Failure, CPLE_UserInterrupt,
    3102               0 :                   "User terminated CreateCopy()" );
    3103               0 :         return CE_Failure;
    3104                 :     }
    3105                 : 
    3106               6 :     GDALDataType eDT = poDstBand->GetRasterDataType();
    3107                 : 
    3108                 :     /* If the destination is compressed, we must try to write blocks just once, to save */
    3109                 :     /* disk space (GTiff case for example), and to avoid data loss (JPEG compression for example) */
    3110               6 :     int bDstIsCompressed = FALSE;
    3111               6 :     const char* pszDstCompressed= CSLFetchNameValue( papszOptions, "COMPRESSED" );
    3112               6 :     if (pszDstCompressed != NULL && CSLTestBoolean(pszDstCompressed))
    3113               4 :         bDstIsCompressed = TRUE;
    3114                 : 
    3115                 : /* -------------------------------------------------------------------- */
    3116                 : /*      What will our swath size be?                                    */
    3117                 : /* -------------------------------------------------------------------- */
    3118                 : 
    3119                 :     int nSwathCols, nSwathLines;
    3120                 :     GDALCopyWholeRasterGetSwathSize(poSrcBand,
    3121                 :                                     poDstBand,
    3122                 :                                     1,
    3123                 :                                     bDstIsCompressed, FALSE,
    3124               6 :                                     &nSwathCols, &nSwathLines);
    3125                 : 
    3126               6 :     int nPixelSize = (GDALGetDataTypeSize(eDT) / 8);
    3127                 : 
    3128               6 :     void *pSwathBuf = VSIMalloc3(nSwathCols, nSwathLines, nPixelSize );
    3129               6 :     if( pSwathBuf == NULL )
    3130                 :     {
    3131                 :         CPLError( CE_Failure, CPLE_OutOfMemory,
    3132                 :                 "Failed to allocate %d*%d*%d byte swath buffer in\n"
    3133                 :                 "GDALRasterBandCopyWholeRaster()",
    3134               0 :                 nSwathCols, nSwathLines, nPixelSize );
    3135               0 :         return CE_Failure;
    3136                 :     }
    3137                 : 
    3138                 :     CPLDebug( "GDAL",
    3139                 :             "GDALRasterBandCopyWholeRaster(): %d*%d swaths",
    3140               6 :             nSwathCols, nSwathLines );
    3141                 : 
    3142                 : /* ==================================================================== */
    3143                 : /*      Band oriented (uninterleaved) case.                             */
    3144                 : /* ==================================================================== */
    3145                 : 
    3146                 :     int iX, iY;
    3147                 : 
    3148              14 :     for( iY = 0; iY < nYSize && eErr == CE_None; iY += nSwathLines )
    3149                 :     {
    3150               8 :         int nThisLines = nSwathLines;
    3151                 : 
    3152               8 :         if( iY + nThisLines > nYSize )
    3153               2 :             nThisLines = nYSize - iY;
    3154                 : 
    3155              16 :         for( iX = 0; iX < nXSize && eErr == CE_None; iX += nSwathCols )
    3156                 :         {
    3157               8 :             int nThisCols = nSwathCols;
    3158                 : 
    3159               8 :             if( iX + nThisCols > nXSize )
    3160               0 :                 nThisCols = nXSize - iX;
    3161                 : 
    3162                 :             eErr = poSrcBand->RasterIO( GF_Read,
    3163                 :                                     iX, iY, nThisCols, nThisLines,
    3164                 :                                     pSwathBuf, nThisCols, nThisLines,
    3165               8 :                                     eDT, 0, 0 );
    3166                 : 
    3167               8 :             if( eErr == CE_None )
    3168                 :                 eErr = poDstBand->RasterIO( GF_Write,
    3169                 :                                         iX, iY, nThisCols, nThisLines,
    3170                 :                                         pSwathBuf, nThisCols, nThisLines,
    3171               8 :                                         eDT, 0, 0 );
    3172                 : 
    3173               8 :             if( eErr == CE_None
    3174                 :                 && !pfnProgress(
    3175                 :                     (iY+nThisLines) / (float) (nYSize),
    3176                 :                     NULL, pProgressData ) )
    3177                 :             {
    3178               0 :                 eErr = CE_Failure;
    3179                 :                 CPLError( CE_Failure, CPLE_UserInterrupt,
    3180               0 :                         "User terminated CreateCopy()" );
    3181                 :             }
    3182                 :         }
    3183                 :     }
    3184                 : 
    3185                 : /* -------------------------------------------------------------------- */
    3186                 : /*      Cleanup                                                         */
    3187                 : /* -------------------------------------------------------------------- */
    3188               6 :     CPLFree( pSwathBuf );
    3189                 : 
    3190               6 :     return eErr;
    3191                 : }

Generated by: LCOV version 1.7