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