38   projector->mSrcCRS = mSrcCRS;
 
   39   projector->mDestCRS = mDestCRS;
 
   40   projector->mTransformContext = mTransformContext;
 
   43   projector->mSrcDatumTransform = mSrcDatumTransform;
 
   44   projector->mDestDatumTransform = mDestDatumTransform;
 
   47   projector->mPrecision = mPrecision;
 
   70                                  int srcDatumTransform,
 
   71                                  int destDatumTransform )
 
   76   mSrcDatumTransform = srcDatumTransform;
 
   77   mDestDatumTransform = destDatumTransform;
 
   85   mTransformContext = transformContext;
 
   87   mSrcDatumTransform = -1;
 
   88   mDestDatumTransform = -1;
 
   94   : mApproximate( false )
 
   95   , mInverseCt( inverseCt )
 
   96   , mDestExtent( extent )
 
  105   , mDestRowsPerMatrixRow( 0.0 )
 
  106   , mDestColsPerMatrixCol( 0.0 )
 
  110   , mSqrTolerance( 0.0 )
 
  133       if ( mExtent.isEmpty() )
 
  135         mExtent = provider->
extent();
 
  140   mDestXRes = mDestExtent.
width() / ( mDestCols );
 
  141   mDestYRes = mDestExtent.height() / ( mDestRows );
 
  147   const double myDestRes = mDestXRes < mDestYRes ? mDestXRes : mDestYRes;
 
  148   mSqrTolerance = myDestRes * myDestRes;
 
  156     mApproximate = 
false;
 
  161   mCPCols = mCPRows = 3;
 
  169   if ( std::fabs( -mDestExtent.yMinimum() - mDestExtent.yMaximum() ) / height < 0.5 * mDestYRes )
 
  172   for ( 
int i = 0; i < mCPRows; i++ )
 
  174     QList<QgsPointXY> myRow;
 
  178     mCPMatrix.insert( i, myRow );
 
  180     QList<bool> myLegalRow;
 
  181     myLegalRow.append( 
bool( 
false ) );
 
  182     myLegalRow.append( 
bool( 
false ) );
 
  183     myLegalRow.append( 
bool( 
false ) );
 
  184     mCPLegalMatrix.insert( i, myLegalRow );
 
  186   for ( 
int i = 0; i < mCPRows; i++ )
 
  188     calcRow( i, inverseCt );
 
  193     const bool myColsOK = checkCols( inverseCt );
 
  196       insertRows( inverseCt );
 
  198     const bool myRowsOK = checkRows( inverseCt );
 
  201       insertCols( inverseCt );
 
  203     if ( myColsOK && myRowsOK )
 
  210     if ( mCPRows * mCPCols > 0.25 * mDestRows * mDestCols )
 
  214       mApproximate = 
false;
 
  222   QgsDebugMsgLevel( QStringLiteral( 
"CPMatrix size: mCPRows = %1 mCPCols = %2" ).arg( mCPRows ).arg( mCPCols ), 4 );
 
  223   mDestRowsPerMatrixRow = 
static_cast< double >( mDestRows ) / ( mCPRows - 1 );
 
  224   mDestColsPerMatrixCol = 
static_cast< double >( mDestCols ) / ( mCPCols - 1 );
 
  234   calcHelper( 0, pHelperTop );
 
  235   calcHelper( 1, pHelperBottom );
 
  241   mSrcYRes = mSrcExtent.height() / mSrcRows;
 
  242   mSrcXRes = mSrcExtent.width() / mSrcCols;
 
  245 ProjectorData::~ProjectorData()
 
  248   delete[] pHelperBottom;
 
  252 void ProjectorData::calcSrcExtent()
 
  263   mSrcExtent = 
QgsRectangle( myPoint.
x(), myPoint.
y(), myPoint.
x(), myPoint.
y() );
 
  264   for ( 
int i = 0; i < mCPRows; i++ )
 
  266     for ( 
int j = 0; j < mCPCols ; j++ )
 
  268       myPoint = mCPMatrix[i][j];
 
  269       if ( mCPLegalMatrix[i][j] )
 
  271         mSrcExtent.combineExtentWith( myPoint.
x(), myPoint.
y() );
 
  278   mSrcExtent = mSrcExtent.intersect( mExtent );
 
  289   if ( !mExtent.isEmpty() )
 
  291     if ( mMaxSrcXRes > 0 )
 
  294       double col = std::floor( ( mSrcExtent.xMinimum() - mExtent.xMinimum() ) / mMaxSrcXRes );
 
  295       double x = mExtent.xMinimum() + col * mMaxSrcXRes;
 
  296       mSrcExtent.setXMinimum( x );
 
  298       col = std::ceil( ( mSrcExtent.xMaximum() - mExtent.xMinimum() ) / mMaxSrcXRes );
 
  299       x = mExtent.xMinimum() + col * mMaxSrcXRes;
 
  300       mSrcExtent.setXMaximum( x );
 
  302     if ( mMaxSrcYRes > 0 )
 
  304       double row = std::floor( ( mExtent.yMaximum() - mSrcExtent.yMaximum() ) / mMaxSrcYRes );
 
  305       double y = mExtent.yMaximum() - row * mMaxSrcYRes;
 
  306       mSrcExtent.setYMaximum( y );
 
  308       row = std::ceil( ( mExtent.yMaximum() - mSrcExtent.yMinimum() ) / mMaxSrcYRes );
 
  309       y = mExtent.yMaximum() - row * mMaxSrcYRes;
 
  310       mSrcExtent.setYMinimum( y );
 
  316 QString ProjectorData::cpToString()
 const 
  319   for ( 
int i = 0; i < mCPRows; i++ )
 
  323     for ( 
int j = 0; j < mCPCols; j++ )
 
  326         myString += QLatin1String( 
"  " );
 
  328       if ( mCPLegalMatrix[i][j] )
 
  334         myString += QLatin1String( 
"(-,-)" );
 
  341 void ProjectorData::calcSrcRowsCols()
 
  349   double myMinSize = std::numeric_limits<double>::max();
 
  353     double myMaxSize = 0;
 
  356     const double myDestColsPerMatrixCell = 
static_cast< double >( mDestCols ) / mCPCols;
 
  357     const double myDestRowsPerMatrixCell = 
static_cast< double >( mDestRows ) / mCPRows;
 
  358     QgsDebugMsgLevel( QStringLiteral( 
"myDestColsPerMatrixCell = %1 myDestRowsPerMatrixCell = %2" ).arg( myDestColsPerMatrixCell ).arg( myDestRowsPerMatrixCell ), 4 );
 
  359     for ( 
int i = 0; i < mCPRows - 1; i++ )
 
  361       for ( 
int j = 0; j < mCPCols - 1; j++ )
 
  364         const QgsPointXY myPointB = mCPMatrix[i][j + 1];
 
  365         const QgsPointXY myPointC = mCPMatrix[i + 1][j];
 
  366         if ( mCPLegalMatrix[i][j] && mCPLegalMatrix[i][j + 1] && mCPLegalMatrix[i + 1][j] )
 
  368           double mySize = std::sqrt( myPointA.
sqrDist( myPointB ) ) / myDestColsPerMatrixCell;
 
  369           if ( mySize < myMinSize )
 
  371           if ( mySize > myMaxSize )
 
  374           mySize = std::sqrt( myPointA.
sqrDist( myPointC ) ) / myDestRowsPerMatrixCell;
 
  375           if ( mySize < myMinSize )
 
  377           if ( mySize > myMaxSize )
 
  385     if ( myMinSize < 0.1 * myMaxSize )
 
  386       myMinSize = 0.1 * myMaxSize;
 
  393     int srcXSize, srcYSize;
 
  396       const double srcXRes = srcExtent.
width() / srcXSize;
 
  397       const double srcYRes = srcExtent.
height() / srcYSize;
 
  398       myMinSize = std::min( srcXRes, srcYRes );
 
  402       QgsDebugMsg( QStringLiteral( 
"Cannot get src extent/size" ) );
 
  411   QgsDebugMsgLevel( QStringLiteral( 
"mMaxSrcXRes = %1 mMaxSrcYRes = %2" ).arg( mMaxSrcXRes ).arg( mMaxSrcYRes ), 4 );
 
  413   const double myMinXSize = mMaxSrcXRes > myMinSize ? mMaxSrcXRes : myMinSize;
 
  414   const double myMinYSize = mMaxSrcYRes > myMinSize ? mMaxSrcYRes : myMinSize;
 
  415   QgsDebugMsgLevel( QStringLiteral( 
"myMinXSize = %1 myMinYSize = %2" ).arg( myMinXSize ).arg( myMinYSize ), 4 );
 
  416   QgsDebugMsgLevel( QStringLiteral( 
"mSrcExtent.width = %1 mSrcExtent.height = %2" ).arg( mSrcExtent.width() ).arg( mSrcExtent.height() ), 4 );
 
  421   double dblSrcRows = mSrcExtent.height() / myMinYSize;
 
  422   if ( dblSrcRows > mDestRows * 10 )
 
  423     mSrcRows = mDestRows * 10;
 
  425     mSrcRows = 
static_cast< int >( std::round( dblSrcRows ) );
 
  427   double dblSrcCols = mSrcExtent.width() / myMinXSize;
 
  428   if ( dblSrcCols > mDestCols * 10 )
 
  429     mSrcCols = mDestCols * 10;
 
  431     mSrcCols = 
static_cast< int >( std::round( dblSrcCols ) );
 
  433   QgsDebugMsgLevel( QStringLiteral( 
"mSrcRows = %1 mSrcCols = %2" ).arg( mSrcRows ).arg( mSrcCols ), 4 );
 
  437 inline void ProjectorData::destPointOnCPMatrix( 
int row, 
int col, 
double *theX, 
double *theY )
 
  439   *theX = mDestExtent.xMinimum() + col * mDestExtent.width() / ( mCPCols - 1 );
 
  440   *theY = mDestExtent.yMaximum() - row * mDestExtent.height() / ( mCPRows - 1 );
 
  443 inline int ProjectorData::matrixRow( 
int destRow )
 
  445   return static_cast< int >( std::floor( ( destRow + 0.5 ) / mDestRowsPerMatrixRow ) );
 
  447 inline int ProjectorData::matrixCol( 
int destCol )
 
  449   return static_cast< int >( std::floor( ( destCol + 0.5 ) / mDestColsPerMatrixCol ) );
 
  452 void ProjectorData::calcHelper( 
int matrixRow, 
QgsPointXY *points )
 
  455   for ( 
int myDestCol = 0; myDestCol < mDestCols; myDestCol++ )
 
  457     const double myDestX = mDestExtent.xMinimum() + ( myDestCol + 0.5 ) * mDestXRes;
 
  459     const int myMatrixCol = matrixCol( myDestCol );
 
  461     double myDestXMin, myDestYMin, myDestXMax, myDestYMax;
 
  463     destPointOnCPMatrix( matrixRow, myMatrixCol, &myDestXMin, &myDestYMin );
 
  464     destPointOnCPMatrix( matrixRow, myMatrixCol + 1, &myDestXMax, &myDestYMax );
 
  466     const double xfrac = ( myDestX - myDestXMin ) / ( myDestXMax - myDestXMin );
 
  468     const QgsPointXY &mySrcPoint0 = mCPMatrix[matrixRow][myMatrixCol];
 
  469     const QgsPointXY &mySrcPoint1 = mCPMatrix[matrixRow][myMatrixCol + 1];
 
  470     const double s = mySrcPoint0.
x() + ( mySrcPoint1.
x() - mySrcPoint0.
x() ) * xfrac;
 
  471     const double t = mySrcPoint0.
y() + ( mySrcPoint1.
y() - mySrcPoint0.
y() ) * xfrac;
 
  473     points[myDestCol].
setX( s );
 
  474     points[myDestCol].
setY( t );
 
  478 void ProjectorData::nextHelper()
 
  483   pHelperTop = pHelperBottom;
 
  485   calcHelper( mHelperTopRow + 2, pHelperBottom );
 
  489 bool ProjectorData::srcRowCol( 
int destRow, 
int destCol, 
int *srcRow, 
int *srcCol )
 
  493     return approximateSrcRowCol( destRow, destCol, srcRow, srcCol );
 
  497     return preciseSrcRowCol( destRow, destCol, srcRow, srcCol );
 
  501 bool ProjectorData::preciseSrcRowCol( 
int destRow, 
int destCol, 
int *srcRow, 
int *srcCol )
 
  503 #if 0 // too slow, even if we only run it on debug builds! 
  505   QgsDebugMsgLevel( QStringLiteral( 
"theDestRow = %1 mDestExtent.yMaximum() = %2 mDestYRes = %3" ).arg( destRow ).arg( mDestExtent.yMaximum() ).arg( mDestYRes ), 5 );
 
  509   double x = mDestExtent.xMinimum() + ( destCol + 0.5 ) * mDestXRes;
 
  510   double y = mDestExtent.yMaximum() - ( destRow + 0.5 ) * mDestYRes;
 
  517   if ( mInverseCt.isValid() )
 
  521       mInverseCt.transformInPlace( x, y, z );
 
  533   if ( !mExtent.contains( x, y ) )
 
  538   *srcRow = 
static_cast< int >( std::floor( ( mSrcExtent.yMaximum() - y ) / mSrcYRes ) );
 
  539   *srcCol = 
static_cast< int >( std::floor( ( x - mSrcExtent.xMinimum() ) / mSrcXRes ) );
 
  541   QgsDebugMsgLevel( QStringLiteral( 
"mSrcExtent.yMinimum() = %1 mSrcExtent.yMaximum() = %2 mSrcYRes = %3" ).arg( mSrcExtent.yMinimum() ).arg( mSrcExtent.yMaximum() ).arg( mSrcYRes ), 5 );
 
  542   QgsDebugMsgLevel( QStringLiteral( 
"theSrcRow = %1 srcCol = %2" ).arg( *srcRow ).arg( *srcCol ), 5 );
 
  549   if ( *srcRow >= mSrcRows ) 
return false;
 
  550   if ( *srcRow < 0 ) 
return false;
 
  551   if ( *srcCol >= mSrcCols ) 
return false;
 
  552   if ( *srcCol < 0 ) 
return false;
 
  557 bool ProjectorData::approximateSrcRowCol( 
int destRow, 
int destCol, 
int *srcRow, 
int *srcCol )
 
  559   const int myMatrixRow = matrixRow( destRow );
 
  560   const int myMatrixCol = matrixCol( destCol );
 
  562   if ( myMatrixRow > mHelperTopRow )
 
  568   const double myDestY = mDestExtent.yMaximum() - ( destRow + 0.5 ) * mDestYRes;
 
  572   double myDestXMin, myDestYMin, myDestXMax, myDestYMax;
 
  574   destPointOnCPMatrix( myMatrixRow + 1, myMatrixCol, &myDestXMin, &myDestYMin );
 
  575   destPointOnCPMatrix( myMatrixRow, myMatrixCol + 1, &myDestXMax, &myDestYMax );
 
  577   const double yfrac = ( myDestY - myDestYMin ) / ( myDestYMax - myDestYMin );
 
  579   const QgsPointXY &myTop = pHelperTop[destCol];
 
  580   const QgsPointXY &myBot = pHelperBottom[destCol];
 
  586   const double tx = myTop.
x();
 
  587   const double ty = myTop.
y();
 
  588   const double bx = myBot.
x();
 
  589   const double by = myBot.
y();
 
  590   const double mySrcX = bx + ( tx - bx ) * yfrac;
 
  591   const double mySrcY = by + ( ty - by ) * yfrac;
 
  593   if ( !mExtent.contains( mySrcX, mySrcY ) )
 
  600   *srcRow = 
static_cast< int >( std::floor( ( mSrcExtent.yMaximum() - mySrcY ) / mSrcYRes ) );
 
  601   *srcCol = 
static_cast< int >( std::floor( ( mySrcX - mSrcExtent.xMinimum() ) / mSrcXRes ) );
 
  606   if ( *srcRow >= mSrcRows ) 
return false;
 
  607   if ( *srcRow < 0 ) 
return false;
 
  608   if ( *srcCol >= mSrcCols ) 
return false;
 
  609   if ( *srcCol < 0 ) 
return false;
 
  616   for ( 
int r = 0; r < mCPRows - 1; r++ )
 
  618     QList<QgsPointXY> myRow;
 
  619     QList<bool> myLegalRow;
 
  620     myRow.reserve( mCPCols );
 
  621     myLegalRow.reserve( mCPCols );
 
  622     for ( 
int c = 0; 
c < mCPCols; ++
c )
 
  625       myLegalRow.append( 
false );
 
  627     QgsDebugMsgLevel( QStringLiteral( 
"insert new row at %1" ).arg( 1 + r * 2 ), 3 );
 
  628     mCPMatrix.insert( 1 + r * 2, myRow );
 
  629     mCPLegalMatrix.insert( 1 + r * 2, myLegalRow );
 
  631   mCPRows += mCPRows - 1;
 
  632   for ( 
int r = 1; r < mCPRows - 1; r += 2 )
 
  640   for ( 
int r = 0; r < mCPRows; r++ )
 
  642     for ( 
int c = 0; 
c < mCPCols - 1; 
c++ )
 
  645       mCPLegalMatrix[r].insert( 1 + 
c * 2, 
false );
 
  648   mCPCols += mCPCols - 1;
 
  649   for ( 
int c = 1; 
c < mCPCols - 1; 
c += 2 )
 
  658   double myDestX, myDestY;
 
  659   destPointOnCPMatrix( row, col, &myDestX, &myDestY );
 
  660   const QgsPointXY myDestPoint( myDestX, myDestY );
 
  665       mCPMatrix[row][col] = ct.
transform( myDestPoint );
 
  666       mCPLegalMatrix[row][col] = 
true;
 
  670       mCPLegalMatrix[row][col] = 
false;
 
  677     mCPLegalMatrix[row][col] = 
false;
 
  684   for ( 
int i = 0; i < mCPCols; i++ )
 
  686     calcCP( row, i, ct );
 
  695   for ( 
int i = 0; i < mCPRows; i++ )
 
  697     calcCP( i, col, ct );
 
  710   for ( 
int c = 0; 
c < mCPCols; 
c++ )
 
  712     for ( 
int r = 1; r < mCPRows - 1; r += 2 )
 
  714       double myDestX, myDestY;
 
  715       destPointOnCPMatrix( r, 
c, &myDestX, &myDestY );
 
  716       const QgsPointXY myDestPoint( myDestX, myDestY );
 
  718       const QgsPointXY mySrcPoint1 = mCPMatrix[r - 1][
c];
 
  720       const QgsPointXY mySrcPoint3 = mCPMatrix[r + 1][
c];
 
  722       const QgsPointXY mySrcApprox( ( mySrcPoint1.
x() + mySrcPoint3.
x() ) / 2, ( mySrcPoint1.
y() + mySrcPoint3.
y() ) / 2 );
 
  723       if ( !mCPLegalMatrix[r - 1][
c] || !mCPLegalMatrix[r][
c] || !mCPLegalMatrix[r + 1][
c] )
 
  730         const QgsPointXY myDestApprox = ct.
transform( mySrcApprox, Qgis::TransformDirection::Reverse );
 
  731         const double mySqrDist = myDestApprox.
sqrDist( myDestPoint );
 
  732         if ( mySqrDist > mSqrTolerance )
 
  755   for ( 
int r = 0; r < mCPRows; r++ )
 
  757     for ( 
int c = 1; 
c < mCPCols - 1; 
c += 2 )
 
  759       double myDestX, myDestY;
 
  760       destPointOnCPMatrix( r, 
c, &myDestX, &myDestY );
 
  762       const QgsPointXY myDestPoint( myDestX, myDestY );
 
  763       const QgsPointXY mySrcPoint1 = mCPMatrix[r][
c - 1];
 
  765       const QgsPointXY mySrcPoint3 = mCPMatrix[r][
c + 1];
 
  767       const QgsPointXY mySrcApprox( ( mySrcPoint1.
x() + mySrcPoint3.
x() ) / 2, ( mySrcPoint1.
y() + mySrcPoint3.
y() ) / 2 );
 
  768       if ( !mCPLegalMatrix[r][
c - 1] || !mCPLegalMatrix[r][
c] || !mCPLegalMatrix[r][
c + 1] )
 
  775         const QgsPointXY myDestApprox = ct.
transform( mySrcApprox, Qgis::TransformDirection::Reverse );
 
  776         const double mySqrDist = myDestApprox.
sqrDist( myDestPoint );
 
  777         if ( mySqrDist > mSqrTolerance )
 
  801       return tr( 
"Approximate" );
 
  803       return tr( 
"Exact" );
 
  805   return QStringLiteral( 
"Unknown" );
 
  811   QgsDebugMsgLevel( QStringLiteral( 
"width = %1 height = %2" ).arg( width ).arg( height ), 4 );
 
  821   if ( ! mSrcCRS.
isValid() || ! mDestCRS.
isValid() || mSrcCRS == mDestCRS )
 
  832   ProjectorData pd( 
extent, width, height, 
mInput, inverseCt, mPrecision, feedback );
 
  837   QgsDebugMsgLevel( QStringLiteral( 
"srcExtent:\n%1" ).arg( pd.srcExtent().toString() ), 4 );
 
  838   QgsDebugMsgLevel( QStringLiteral( 
"srcCols = %1 srcRows = %2" ).arg( pd.srcCols() ).arg( pd.srcRows() ), 4 );
 
  841   if ( pd.srcRows() <= 0 || pd.srcCols() <= 0 )
 
  847   std::unique_ptr< QgsRasterBlock > inputBlock( 
mInput->
block( bandNo, pd.srcExtent(), pd.srcCols(), pd.srcRows(), feedback ) );
 
  848   if ( !inputBlock || inputBlock->isEmpty() )
 
  850     QgsDebugMsg( QStringLiteral( 
"No raster data!" ) );
 
  856   std::unique_ptr< QgsRasterBlock > outputBlock( 
new QgsRasterBlock( inputBlock->dataType(), width, height ) );
 
  857   if ( inputBlock->hasNoDataValue() )
 
  859     outputBlock->setNoDataValue( inputBlock->noDataValue() );
 
  861   if ( !outputBlock->isValid() )
 
  863     QgsDebugMsg( QStringLiteral( 
"Cannot create block" ) );
 
  864     return outputBlock.release();
 
  868   outputBlock->setIsNoData();
 
  882   outputBlock->setIsNoData();
 
  885   for ( 
int i = 0; i < height; ++i )
 
  889     for ( 
int j = 0; j < width; ++j )
 
  891       const bool inside = pd.srcRowCol( i, j, &srcRow, &srcCol );
 
  892       if ( !inside ) 
continue; 
 
  894       const qgssize srcIndex = 
static_cast< qgssize >( srcRow ) * pd.srcCols() + srcCol;
 
  897       if ( doNoData && inputBlock->isNoData( srcRow, srcCol ) )
 
  899         outputBlock->setIsNoData( i, j );
 
  903       const qgssize destIndex = 
static_cast< qgssize >( i ) * width + j;
 
  904       char *srcBits = inputBlock->bits( srcIndex );
 
  905       char *destBits = outputBlock->bits( destIndex );
 
  916       memcpy( destBits, srcBits, pixelSize );
 
  917       outputBlock->setIsData( i, j );
 
  921   return outputBlock.release();
 
  925     QgsRectangle &destExtent, 
int &destXSize, 
int &destYSize )
 
  927   if ( srcExtent.
isEmpty() || srcXSize <= 0 || srcYSize <= 0 )
 
  937   return extentSize( ct, srcExtent, srcXSize, srcYSize, destExtent, destXSize, destYSize );
 
  941                                      const QgsRectangle &srcExtent, 
int srcXSize, 
int srcYSize,
 
  942                                      QgsRectangle &destExtent, 
int &destXSize, 
int &destYSize )
 
  944   if ( srcExtent.
isEmpty() || srcXSize <= 0 || srcYSize <= 0 )
 
  956   constexpr 
int steps = 3;
 
  957   const double srcXStep = srcExtent.
width() / steps;
 
  958   const double srcYStep = srcExtent.
height() / steps;
 
  959   const double srcXRes = srcExtent.
width() / srcXSize;
 
  960   const double srcYRes = srcExtent.
height() / srcYSize;
 
  961   double destXRes = std::numeric_limits<double>::max();
 
  962   double destYRes = std::numeric_limits<double>::max();
 
  966   for ( 
int i = 0; i < steps; i++ )
 
  968     const double x = srcExtent.
xMinimum() + i * srcXStep;
 
  969     for ( 
int j = 0; j < steps; j++ )
 
  971       const double y = srcExtent.
yMinimum() + j * srcYStep;
 
  972       const QgsRectangle srcRectangle( x - srcXRes / 2, y - srcYRes / 2, x + srcXRes / 2, y + srcYRes / 2 );
 
  976         if ( destRectangle.
width() > 0 )
 
  978           destXRes = std::min( destXRes, destRectangle.
width() );
 
  979           if ( destRectangle.
width() > maxXRes )
 
  980             maxXRes = destRectangle.
width();
 
  982         if ( destRectangle.
height() > 0 )
 
  984           destYRes = std::min( destYRes, destRectangle.
height() );
 
  985           if ( destRectangle.
height() > maxYRes )
 
  986             maxYRes = destRectangle.
height();
 
  999   if ( destXRes < 0.1 * maxXRes )
 
 1001     destXRes = 0.1 * maxXRes;
 
 1003   if ( destYRes < 0.1 * maxYRes )
 
 1005     destYRes = 0.1 * maxYRes;
 
 1007   if ( destXRes == 0 || destExtent.
width() / destXRes  > std::numeric_limits<int>::max() )
 
 1009   if ( destYRes == 0 || destExtent.
height() / destYRes  > std::numeric_limits<int>::max() )
 
 1012   destXSize = std::max( 1, 
static_cast< int >( destExtent.
width() / destXRes ) );
 
 1013   destYSize = std::max( 1, 
static_cast< int >( destExtent.
height() / destYRes ) );