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 

doxygen1.2.3-20001105 Dimitri van Heesch, © 1997-2000