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