Main Page Class Hierarchy Compound List File List Compound Members File Members Related Pages

# rasterio.cpp

    00001 /******************************************************************************
    00002  * $Id: rasterio_cpp-source.html,v 1.5 2000/11/06 04:49:01 warmerda Exp $
    00003  *
    00004  * Project:  GDAL Core
    00005  * Purpose:  Contains default implementation of GDALRasterBand::IRasterIO()
    00006  *           and supporting functions of broader utility.
    00007  * Author:   Frank Warmerdam, warmerda@home.com
    00008  *
    00009  ******************************************************************************
    00010  * Copyright (c) 1998, Frank Warmerdam
    00011  *
    00012  * Permission is hereby granted, free of charge, to any person obtaining a
    00013  * copy of this software and associated documentation files (the "Software"),
    00014  * to deal in the Software without restriction, including without limitation
    00015  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    00016  * and/or sell copies of the Software, and to permit persons to whom the
    00017  * Software is furnished to do so, subject to the following conditions:
    00018  *
    00019  * The above copyright notice and this permission notice shall be included
    00020  * in all copies or substantial portions of the Software.
    00021  *
    00022  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    00023  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    00024  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    00025  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    00026  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    00027  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    00028  * DEALINGS IN THE SOFTWARE.
    00029  ******************************************************************************
    00030  *
    00031  * $Log: rasterio_cpp-source.html,v $
    00031  * Revision 1.5  2000/11/06 04:49:01  warmerda
    00031  * *** empty log message ***
    00031  *
    00032  * Revision 1.13  2000/08/16 15:50:52  warmerda
    00033  * fixed some bugs with floating (datasetless) bands
    00034  *
    00035  * Revision 1.12  2000/07/13 13:08:53  warmerda
    00036  * fixed GDALSwapWords with skip value different from word size
    00037  *
    00038  * Revision 1.11  2000/06/05 17:24:05  warmerda
    00039  * added real complex support
    00040  *
    00041  * Revision 1.10  2000/05/15 14:33:49  warmerda
    00042  * don't crash on read failure
    00043  *
    00044  * Revision 1.9  2000/04/04 15:25:13  warmerda
    00045  * Fixed embarrasing bug in GDALCopyWords() for some cases.
    00046  *
    00047  * Revision 1.8  2000/03/06 18:57:07  warmerda
    00048  * Fixed bug in 1:1 special case code.
    00049  *
    00050  * Revision 1.7  2000/03/06 02:22:13  warmerda
    00051  * added overview support
    00052  *
    00053  * Revision 1.6  1999/11/23 18:44:10  warmerda
    00054  * Fixed GDALCopyWords!
    00055  *
    00056  * Revision 1.5  1999/07/23 19:36:09  warmerda
    00057  * added support for data type translation and a swapping function
    00058  *
    00059  * Revision 1.4  1999/01/11 15:38:38  warmerda
    00060  * Added optimized case for simple 1:1 copies.
    00061  *
    00062  * Revision 1.3  1999/01/02 21:14:01  warmerda
    00063  * Added write support
    00064  *
    00065  * Revision 1.2  1998/12/31 18:54:25  warmerda
    00066  * Implement initial GDALRasterBlock support, and block cache
    00067  *
    00068  * Revision 1.1  1998/12/06 22:15:42  warmerda
    00069  * New
    00070  */
    00071
    00072 #include "gdal_priv.h"
    00073
    00074 /************************************************************************/
    00075 /*                             IRasterIO()                              */
    00076 /*                                                                      */
    00077 /*      Default internal implementation of RasterIO() ... utilizes      */
    00078 /*      the Block access methods to satisfy the request.  This would    */
    00079 /*      normally only be overridden by formats with overviews.          */
    00080 /************************************************************************/
    00081
    00082 CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
    00083                                   int nXOff, int nYOff, int nXSize, int nYSize,
    00084                                   void * pData, int nBufXSize, int nBufYSize,
    00085                                   GDALDataType eBufType,
    00086                                   int nPixelSpace, int nLineSpace )
    00087
    00088 {
    00089     int         nBandDataSize = GDALGetDataTypeSize( eDataType ) / 8;
    00090     GByte       *pabySrcBlock = NULL;
    00091     GDALRasterBlock *poBlock;
    00092     int         nLBlockX=-1, nLBlockY=-1, iBufYOff, iBufXOff, iSrcY;
    00093
    00094 /* ==================================================================== */
    00095 /*      A common case is the data requested with it's inherent data     */
    00096 /*      type, the destination is packed, and the block width is the     */
    00097 /*      raster width.                                                   */
    00098 /* ==================================================================== */
    00099     if( eBufType == eDataType
    00100         && nPixelSpace == GDALGetDataTypeSize(eBufType)/8
    00101         && nLineSpace == nPixelSpace * nXSize
    00102         && nBlockXSize == GetXSize()
    00103         && nBufXSize == nXSize
    00104         && nBufYSize == nYSize )
    00105     {
    00106         for( iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff++ )
    00107         {
    00108             int         nSrcByteOffset;
    00109
    00110             iSrcY = iBufYOff + nYOff;
    00111
    00112             if( iSrcY < nLBlockY * nBlockYSize
    00113                 || iSrcY >= (nLBlockY+1) * nBlockYSize )
    00114             {
    00115                 nLBlockY = iSrcY / nBlockYSize;
    00116
    00117                 poBlock = GetBlockRef( 0, nLBlockY );
    00118                 if( poBlock == NULL )
    00119                 {
    00120                     return( CE_Failure );
    00121                 }
    00122
    00123                 if( eRWFlag == GF_Write )
    00124                     poBlock->MarkDirty();
    00125
    00126                 pabySrcBlock = (GByte *) poBlock->GetDataRef();
    00127             }
    00128
    00129             nSrcByteOffset = ((iSrcY-nLBlockY*nBlockYSize)*nBlockXSize + nXOff)
    00130                 * nPixelSpace;
    00131
    00132             if( eRWFlag == GF_Write )
    00133                 memcpy( pabySrcBlock + nSrcByteOffset,
    00134                         ((GByte *) pData) + iBufYOff * nLineSpace,
    00135                         nLineSpace );
    00136             else
    00137                 memcpy( ((GByte *) pData) + iBufYOff * nLineSpace,
    00138                         pabySrcBlock + nSrcByteOffset,
    00139                         nLineSpace );
    00140         }
    00141
    00142         return CE_None;
    00143     }
    00144
    00145 /* ==================================================================== */
    00146 /*      Do we have overviews that would be appropriate to satisfy       */
    00147 /*      this request?                                                   */
    00148 /* ==================================================================== */
    00149     if( (nBufXSize < nXSize || nBufYSize < nYSize)
    00150         && GetOverviewCount() > 0 && eRWFlag == GF_Read )
    00151     {
    00152         if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
    00153                               pData, nBufXSize, nBufYSize,
    00154                               eBufType, nPixelSpace, nLineSpace ) == CE_None )
    00155             return CE_None;
    00156     }
    00157
    00158 /* ==================================================================== */
    00159 /*      Loop reading required source blocks to satisfy output           */
    00160 /*      request.  This is the most general implementation.              */
    00161 /* ==================================================================== */
    00162
    00163 /* -------------------------------------------------------------------- */
    00164 /*      Compute stepping increment.                                     */
    00165 /* -------------------------------------------------------------------- */
    00166     double      dfSrcX, dfSrcY, dfSrcXInc, dfSrcYInc;
    00167     int         iSrcX;
    00168
    00169     dfSrcXInc = nXSize / (double) nBufXSize;
    00170     dfSrcYInc = nYSize / (double) nBufYSize;
    00171
    00172 /* -------------------------------------------------------------------- */
    00173 /*      Loop over buffer computing source locations.                    */
    00174 /* -------------------------------------------------------------------- */
    00175     for( iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff++ )
    00176     {
    00177         int     iBufOffset, iSrcOffset;
    00178
    00179         dfSrcY = (iBufYOff+0.5) * dfSrcYInc + nYOff;
    00180         iSrcY = (int) dfSrcY;
    00181
    00182         iBufOffset = iBufYOff * nLineSpace;
    00183
    00184         for( iBufXOff = 0; iBufXOff < nBufXSize; iBufXOff++ )
    00185         {
    00186             dfSrcX = (iBufXOff+0.5) * dfSrcXInc + nXOff;
    00187
    00188             iSrcX = (int) dfSrcX;
    00189
    00190 /* -------------------------------------------------------------------- */
    00191 /*      Ensure we have the appropriate block loaded.                    */
    00192 /* -------------------------------------------------------------------- */
    00193             if( iSrcX < nLBlockX * nBlockXSize
    00194                 || iSrcX >= (nLBlockX+1) * nBlockXSize
    00195                 || iSrcY < nLBlockY * nBlockYSize
    00196                 || iSrcY >= (nLBlockY+1) * nBlockYSize )
    00197             {
    00198                 nLBlockX = iSrcX / nBlockXSize;
    00199                 nLBlockY = iSrcY / nBlockYSize;
    00200
    00201                 poBlock = GetBlockRef( nLBlockX, nLBlockY );
    00202                 if( poBlock == NULL )
    00203                 {
    00204                     return( CE_Failure );
    00205                 }
    00206
    00207                 if( eRWFlag == GF_Write )
    00208                     poBlock->MarkDirty();
    00209
    00210                 pabySrcBlock = (GByte *) poBlock->GetDataRef();
    00211                 if( pabySrcBlock == NULL )
    00212                     return CE_Failure;
    00213             }
    00214
    00215 /* -------------------------------------------------------------------- */
    00216 /*      Copy over this pixel of data.                                   */
    00217 /* -------------------------------------------------------------------- */
    00218             iSrcOffset = (iSrcX - nLBlockX*nBlockXSize
    00219                 + (iSrcY - nLBlockY*nBlockYSize) * nBlockXSize)*nBandDataSize;
    00220
    00221             if( eDataType == eBufType )
    00222             {
    00223                 if( eRWFlag == GF_Read )
    00224                     memcpy( ((GByte *) pData) + iBufOffset,
    00225                             pabySrcBlock + iSrcOffset, nBandDataSize );
    00226                 else
    00227                     memcpy( pabySrcBlock + iSrcOffset,
    00228                             ((GByte *) pData) + iBufOffset, nBandDataSize );
    00229             }
    00230             else
    00231             {
    00232                 /* type to type conversion ... ouch, this is expensive way
    00233                    of handling single words */
    00234
    00235                 if( eRWFlag == GF_Read )
    00236                     GDALCopyWords( pabySrcBlock + iSrcOffset, eDataType, 0,
    00237                                    ((GByte *) pData) + iBufOffset, eBufType, 0,
    00238                                    1 );
    00239                 else
    00240                     GDALCopyWords( ((GByte *) pData) + iBufOffset, eBufType, 0,
    00241                                    pabySrcBlock + iSrcOffset, eDataType, 0,
    00242                                    1 );
    00243             }
    00244
    00245             iBufOffset += nPixelSpace;
    00246         }
    00247     }
    00248
    00249     return( CE_None );
    00250 }
    00251
    00252 /************************************************************************/
    00253 /*                           GDALSwapWords()                            */
    00254 /************************************************************************/
    00255
    00256 void GDALSwapWords( void *pData, int nWordSize, int nWordCount,
    00257                     int nWordSkip )
    00258
    00259 {
    00260     int         i;
    00261     GByte       *pabyData = (GByte *) pData;
    00262
    00263     switch( nWordSize )
    00264     {
    00265       case 1:
    00266         break;
    00267
    00268       case 2:
    00269         CPLAssert( nWordSize >= 2 );
    00270         for( i = 0; i < nWordCount; i++ )
    00271         {
    00272             GByte       byTemp;
    00273
    00274             byTemp = pabyData[0];
    00275             pabyData[0] = pabyData[1];
    00276             pabyData[1] = byTemp;
    00277
    00278             pabyData += nWordSkip;
    00279         }
    00280         break;
    00281
    00282       case 4:
    00283         CPLAssert( nWordSize >= 4 );
    00284         for( i = 0; i < nWordCount; i++ )
    00285         {
    00286             GByte       byTemp;
    00287
    00288             byTemp = pabyData[0];
    00289             pabyData[0] = pabyData[3];
    00290             pabyData[3] = byTemp;
    00291
    00292             byTemp = pabyData[1];
    00293             pabyData[1] = pabyData[2];
    00294             pabyData[2] = byTemp;
    00295
    00296             pabyData += nWordSkip;
    00297         }
    00298         break;
    00299
    00300       case 8:
    00301         CPLAssert( nWordSize >= 8 );
    00302         for( i = 0; i < nWordCount; i++ )
    00303         {
    00304             GByte       byTemp;
    00305
    00306             byTemp = pabyData[0];
    00307             pabyData[0] = pabyData[7];
    00308             pabyData[7] = byTemp;
    00309
    00310             byTemp = pabyData[1];
    00311             pabyData[1] = pabyData[6];
    00312             pabyData[6] = byTemp;
    00313
    00314             byTemp = pabyData[2];
    00315             pabyData[2] = pabyData[5];
    00316             pabyData[5] = byTemp;
    00317
    00318             byTemp = pabyData[3];
    00319             pabyData[3] = pabyData[4];
    00320             pabyData[4] = byTemp;
    00321
    00322             pabyData += nWordSkip;
    00323         }
    00324         break;
    00325
    00326       default:
    00327         CPLAssert( FALSE );
    00328     }
    00329 }
    00330
    00331 /************************************************************************/
    00332 /*                           GDALCopyWords()                            */
    00333 /************************************************************************/
    00334
    00335 void
    00336 GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
    00337                void * pDstData, GDALDataType eDstType, int nDstPixelOffset,
    00338                int nWordCount )
    00339
    00340 {
    00341 /* -------------------------------------------------------------------- */
    00342 /*      Special case when no data type translation is required.         */
    00343 /* -------------------------------------------------------------------- */
    00344     if( eSrcType == eDstType )
    00345     {
    00346         int     nWordSize = GDALGetDataTypeSize(eSrcType)/8;
    00347         int     i;
    00348
    00349         // contiguous blocks.
    00350         if( nWordSize == nSrcPixelOffset && nWordSize == nDstPixelOffset )
    00351         {
    00352             memcpy( pDstData, pSrcData, nSrcPixelOffset * nWordCount );
    00353             return;
    00354         }
    00355
    00356         // source or destination is not contiguous
    00357         for( i = 0; i < nWordCount; i++ )
    00358         {
    00359             memcpy( ((GByte *)pDstData) + i * nDstPixelOffset,
    00360                     ((GByte *)pSrcData) + i * nSrcPixelOffset,
    00361                     nWordSize );
    00362         }
    00363
    00364         return;
    00365     }
    00366
    00367 /* ==================================================================== */
    00368 /*      General translation case                                        */
    00369 /* ==================================================================== */
    00370     for( int iWord = 0; iWord < nWordCount; iWord++ )
    00371     {
    00372         GByte   *pabySrcWord, *pabyDstWord;
    00373         double  dfPixelValue, dfPixelValueI=0.0;
    00374
    00375         pabySrcWord = ((GByte *) pSrcData) + iWord * nSrcPixelOffset;
    00376
    00377 /* -------------------------------------------------------------------- */
    00378 /*      Fetch source value based on data type.                          */
    00379 /* -------------------------------------------------------------------- */
    00380         switch( eSrcType )
    00381         {
    00382           case GDT_Byte:
    00383             dfPixelValue = *pabySrcWord;
    00384             break;
    00385
    00386           case GDT_UInt16:
    00387           {
    00388               GUInt16   nVal;
    00389
    00390               memcpy( &nVal, pabySrcWord, 2 );
    00391               dfPixelValue = nVal;
    00392           }
    00393           break;
    00394
    00395           case GDT_Int16:
    00396           {
    00397               GInt16    nVal;
    00398
    00399               memcpy( &nVal, pabySrcWord, 2 );
    00400               dfPixelValue = nVal;
    00401           }
    00402           break;
    00403
    00404           case GDT_Int32:
    00405           {
    00406               GInt32    nVal;
    00407
    00408               memcpy( &nVal, pabySrcWord, 4 );
    00409               dfPixelValue = nVal;
    00410           }
    00411           break;
    00412
    00413           case GDT_UInt32:
    00414           {
    00415               GUInt32   nVal;
    00416
    00417               memcpy( &nVal, pabySrcWord, 4 );
    00418               dfPixelValue = nVal;
    00419           }
    00420           break;
    00421
    00422           case GDT_Float32:
    00423           {
    00424               float     fVal;
    00425
    00426               memcpy( &fVal, pabySrcWord, 4 );
    00427               dfPixelValue = fVal;
    00428           }
    00429           break;
    00430
    00431           case GDT_Float64:
    00432           {
    00433               memcpy( &dfPixelValue, pabySrcWord, 8 );
    00434           }
    00435           break;
    00436
    00437           case GDT_CInt16:
    00438           {
    00439               GInt16    nVal;
    00440
    00441               memcpy( &nVal, pabySrcWord, 2 );
    00442               dfPixelValue = nVal;
    00443               memcpy( &nVal, pabySrcWord+2, 2 );
    00444               dfPixelValueI = nVal;
    00445           }
    00446           break;
    00447
    00448           case GDT_CInt32:
    00449           {
    00450               GInt32    nVal;
    00451
    00452               memcpy( &nVal, pabySrcWord, 4 );
    00453               dfPixelValue = nVal;
    00454               memcpy( &nVal, pabySrcWord+4, 4 );
    00455               dfPixelValueI = nVal;
    00456           }
    00457           break;
    00458
    00459           case GDT_CFloat32:
    00460           {
    00461               float     fVal;
    00462
    00463               memcpy( &fVal, pabySrcWord, 4 );
    00464               dfPixelValue = fVal;
    00465               memcpy( &fVal, pabySrcWord+4, 4 );
    00466               dfPixelValueI = fVal;
    00467           }
    00468           break;
    00469
    00470           case GDT_CFloat64:
    00471           {
    00472               memcpy( &dfPixelValue, pabySrcWord, 8 );
    00473               memcpy( &dfPixelValueI, pabySrcWord+8, 8 );
    00474           }
    00475           break;
    00476
    00477           default:
    00478             CPLAssert( FALSE );
    00479         }
    00480
    00481 /* -------------------------------------------------------------------- */
    00482 /*      Set the destination pixel, doing range clipping as needed.      */
    00483 /* -------------------------------------------------------------------- */
    00484         pabyDstWord = ((GByte *) pDstData) + iWord * nDstPixelOffset;
    00485         switch( eDstType )
    00486         {
    00487           case GDT_Byte:
    00488           {
    00489               if( dfPixelValue < 0.0 )
    00490                   *pabyDstWord = 0;
    00491               else if( dfPixelValue > 255.0 )
    00492                   *pabyDstWord = 255;
    00493               else
    00494                   *pabyDstWord = (GByte) dfPixelValue;
    00495           }
    00496           break;
    00497
    00498           case GDT_UInt16:
    00499           {
    00500               GUInt16   nVal;
    00501
    00502               if( dfPixelValue < 0.0 )
    00503                   nVal = 0;
    00504               else if( dfPixelValue > 65535.0 )
    00505                   nVal = 65535;
    00506               else
    00507                   nVal = (GUInt16) dfPixelValue;
    00508
    00509               memcpy( pabyDstWord, &nVal, 2 );
    00510           }
    00511           break;
    00512
    00513           case GDT_Int16:
    00514           {
    00515               GInt16    nVal;
    00516
    00517               if( dfPixelValue < -32768 )
    00518                   nVal = -32768;
    00519               else if( dfPixelValue > 32767 )
    00520                   nVal = 32767;
    00521               else
    00522                   nVal = (GInt16) dfPixelValue;
    00523
    00524               memcpy( pabyDstWord, &nVal, 2 );
    00525           }
    00526           break;
    00527
    00528           case GDT_UInt32:
    00529           {
    00530               GUInt32   nVal;
    00531
    00532               if( dfPixelValue < 0 )
    00533                   nVal = 0;
    00534               else if( dfPixelValue > 4294967295U )
    00535                   nVal = 4294967295U;
    00536               else
    00537                   nVal = (GInt32) dfPixelValue;
    00538
    00539               memcpy( pabyDstWord, &nVal, 4 );
    00540           }
    00541           break;
    00542
    00543           case GDT_Int32:
    00544           {
    00545               GInt32    nVal;
    00546
    00547               if( dfPixelValue < -2147483647.0 )
    00548                   nVal = -2147483647;
    00549               else if( dfPixelValue > 2147483647 )
    00550                   nVal = 2147483647;
    00551               else
    00552                   nVal = (GInt32) dfPixelValue;
    00553
    00554               memcpy( pabyDstWord, &nVal, 4 );
    00555           }
    00556           break;
    00557
    00558           case GDT_Float32:
    00559           {
    00560               float     fVal;
    00561
    00562               fVal = dfPixelValue;
    00563
    00564               memcpy( pabyDstWord, &fVal, 4 );
    00565           }
    00566           break;
    00567
    00568           case GDT_Float64:
    00569               memcpy( pabyDstWord, &dfPixelValue, 8 );
    00570               break;
    00571
    00572           case GDT_CInt16:
    00573           {
    00574               GInt16    nVal;
    00575
    00576               if( dfPixelValue < -32768 )
    00577                   nVal = -32768;
    00578               else if( dfPixelValue > 32767 )
    00579                   nVal = 32767;
    00580               else
    00581                   nVal = (GInt16) dfPixelValue;
    00582               memcpy( pabyDstWord, &nVal, 2 );
    00583
    00584               if( dfPixelValueI < -32768 )
    00585                   nVal = -32768;
    00586               else if( dfPixelValueI > 32767 )
    00587                   nVal = 32767;
    00588               else
    00589                   nVal = (GInt16) dfPixelValueI;
    00590               memcpy( pabyDstWord+2, &nVal, 2 );
    00591           }
    00592           break;
    00593
    00594           case GDT_CInt32:
    00595           {
    00596               GInt32    nVal;
    00597
    00598               if( dfPixelValue < -2147483647.0 )
    00599                   nVal = -2147483647;
    00600               else if( dfPixelValue > 2147483647 )
    00601                   nVal = 2147483647;
    00602               else
    00603                   nVal = (GInt32) dfPixelValue;
    00604
    00605               memcpy( pabyDstWord, &nVal, 4 );
    00606
    00607               if( dfPixelValueI < -2147483647.0 )
    00608                   nVal = -2147483647;
    00609               else if( dfPixelValueI > 2147483647 )
    00610                   nVal = 2147483647;
    00611               else
    00612                   nVal = (GInt32) dfPixelValueI;
    00613
    00614               memcpy( pabyDstWord+4, &nVal, 4 );
    00615           }
    00616           break;
    00617
    00618           case GDT_CFloat32:
    00619           {
    00620               float     fVal;
    00621
    00622               fVal = dfPixelValue;
    00623               memcpy( pabyDstWord, &fVal, 4 );
    00624               fVal = dfPixelValueI;
    00625               memcpy( pabyDstWord+4, &fVal, 4 );
    00626           }
    00627           break;
    00628
    00629           case GDT_CFloat64:
    00630               memcpy( pabyDstWord, &dfPixelValue, 8 );
    00631               memcpy( pabyDstWord+8, &dfPixelValueI, 8 );
    00632               break;
    00633
    00634           default:
    00635             CPLAssert( FALSE );
    00636         }
    00637     } /* next iWord */
    00638 }
    00639
    00640 /************************************************************************/
    00641 /*                          OverviewRasterIO()                          */
    00642 /*                                                                      */
    00643 /*      Special work function to utilize available overviews to         */
    00644 /*      more efficiently satisfy downsampled requests.  It will         */
    00645 /*      return CE_Failure if there are no appropriate overviews         */
    00646 /*      available but it doesn't emit any error messages.               */
    00647 /************************************************************************/
    00648
    00649 CPLErr GDALRasterBand::OverviewRasterIO( GDALRWFlag eRWFlag,
    00650                                 int nXOff, int nYOff, int nXSize, int nYSize,
    00651                                 void * pData, int nBufXSize, int nBufYSize,
    00652                                 GDALDataType eBufType,
    00653                                 int nPixelSpace, int nLineSpace )
    00654
    00655
    00656 {
    00657     GDALRasterBand      *poBestOverview = NULL;
    00658     int                 nOverviewCount = GetOverviewCount();
    00659     double              dfDesiredResolution, dfBestResolution = 1.0;
    00660
    00661 /* -------------------------------------------------------------------- */
    00662 /*      Find the Compute the desired resolution.  The resolution is     */
    00663 /*      based on the least reduced axis, and represents the number      */
    00664 /*      of source pixels to one destination pixel.                      */
    00665 /* -------------------------------------------------------------------- */
    00666     if( (nXSize / (double) nBufXSize) < (nYSize / (double) nBufYSize )
    00667         || nBufYSize == 1 )
    00668         dfDesiredResolution = nXSize / (double) nBufXSize;
    00669     else
    00670         dfDesiredResolution = nYSize / (double) nBufYSize;
    00671
    00672 /* -------------------------------------------------------------------- */
    00673 /*      Find the overview level that largest resolution value (most     */
    00674 /*      downsampled) that is still less than (or only a little more)    */
    00675 /*      downsampled than the request.                                   */
    00676 /* -------------------------------------------------------------------- */
    00677     for( int iOverview = 0; iOverview < nOverviewCount; iOverview++ )
    00678     {
    00679         GDALRasterBand  *poOverview = GetOverview( iOverview );
    00680         double          dfResolution;
    00681
    00682         if( (GetXSize() / (double) poOverview->GetXSize())
    00683             < (GetYSize() / (double) poOverview->GetYSize()) )
    00684             dfResolution =
    00685                 GetXSize() / (double) poOverview->GetXSize();
    00686         else
    00687             dfResolution =
    00688                 GetYSize() / (double) poOverview->GetYSize();
    00689
    00690         if( dfResolution < dfDesiredResolution * 1.2
    00691             && dfResolution > dfBestResolution )
    00692         {
    00693             poBestOverview = poOverview;
    00694             dfBestResolution = dfResolution;
    00695         }
    00696     }
    00697
    00698 /* -------------------------------------------------------------------- */
    00699 /*      If we didn't find an overview that helps us, just return        */
    00700 /*      indicating failure and the full resolution image will be used.  */
    00701 /* -------------------------------------------------------------------- */
    00702     if( poBestOverview == NULL )
    00703         return CE_Failure;
    00704
    00705 /* -------------------------------------------------------------------- */
    00706 /*      Recompute the source window in terms of the selected            */
    00707 /*      overview.                                                       */
    00708 /* -------------------------------------------------------------------- */
    00709     int         nOXOff, nOYOff, nOXSize, nOYSize;
    00710     double      dfXRes, dfYRes;
    00711
    00712     dfXRes = GetXSize() / (double) poBestOverview->GetXSize();
    00713     dfYRes = GetYSize() / (double) poBestOverview->GetYSize();
    00714
    00715     nOXOff = MIN(poBestOverview->GetXSize()-1,(int) (nXOff/dfXRes+0.5));
    00716     nOYOff = MIN(poBestOverview->GetYSize()-1,(int) (nYOff/dfYRes+0.5));
    00717     nOXSize = MAX(1,(int) (nXSize/dfXRes + 0.5));
    00718     nOYSize = MAX(1,(int) (nYSize/dfYRes + 0.5));
    00719     if( nOXOff + nOXSize > poBestOverview->GetXSize() )
    00720         nOXSize = poBestOverview->GetXSize() - nOXOff;
    00721     if( nOYOff + nOYSize > poBestOverview->GetYSize() )
    00722         nOYSize = poBestOverview->GetYSize() - nOYOff;
    00723
    00724 /* -------------------------------------------------------------------- */
    00725 /*      Recast the call in terms of the new raster layer.               */
    00726 /* -------------------------------------------------------------------- */
    00727     return poBestOverview->RasterIO( eRWFlag, nOXOff, nOYOff, nOXSize, nOYSize,
    00728                                      pData, nBufXSize, nBufYSize, eBufType,
    00729                                      nPixelSpace, nLineSpace );
    00730 }
    00731