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