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
1.2.3-20001105 written by Dimitri van Heesch,
© 1997-2000