QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
qgscubicrasterresampler.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscubicrasterresampler.cpp
3  ----------------------------
4  begin : December 2011
5  copyright : (C) 2011 by Marco Hugentobler
6  email : marco at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 #include <QImage>
20 #include <cmath>
21 
23 {
24  return new QgsCubicRasterResampler();
25 }
26 
27 void QgsCubicRasterResampler::resample( const QImage &srcImage, QImage &dstImage )
28 {
29  int nCols = srcImage.width();
30  int nRows = srcImage.height();
31 
32  int pos = 0;
33  QRgb px;
34  int *redMatrix = new int[ nCols * nRows ];
35  int *greenMatrix = new int[ nCols * nRows ];
36  int *blueMatrix = new int[ nCols * nRows ];
37  int *alphaMatrix = new int[ nCols * nRows ];
38 
39  for ( int heightIndex = 0; heightIndex < nRows; ++heightIndex )
40  {
41  QRgb *scanLine = ( QRgb * )srcImage.constScanLine( heightIndex );
42  for ( int widthIndex = 0; widthIndex < nCols; ++widthIndex )
43  {
44  px = scanLine[widthIndex];
45  int alpha = qAlpha( px );
46  alphaMatrix[pos] = alpha;
47  redMatrix[pos] = qRed( px );
48  greenMatrix[pos] = qGreen( px );
49  blueMatrix[pos] = qBlue( px );
50 
51  pos++;
52  }
53  }
54 
55  //derivative x
56  double *xDerivativeMatrixRed = new double[ nCols * nRows ];
57  xDerivativeMatrix( nCols, nRows, xDerivativeMatrixRed, redMatrix );
58  double *xDerivativeMatrixGreen = new double[ nCols * nRows ];
59  xDerivativeMatrix( nCols, nRows, xDerivativeMatrixGreen, greenMatrix );
60  double *xDerivativeMatrixBlue = new double[ nCols * nRows ];
61  xDerivativeMatrix( nCols, nRows, xDerivativeMatrixBlue, blueMatrix );
62  double *xDerivativeMatrixAlpha = new double[ nCols * nRows ];
63  xDerivativeMatrix( nCols, nRows, xDerivativeMatrixAlpha, alphaMatrix );
64 
65  //derivative y
66  double *yDerivativeMatrixRed = new double[ nCols * nRows ];
67  yDerivativeMatrix( nCols, nRows, yDerivativeMatrixRed, redMatrix );
68  double *yDerivativeMatrixGreen = new double[ nCols * nRows ];
69  yDerivativeMatrix( nCols, nRows, yDerivativeMatrixGreen, greenMatrix );
70  double *yDerivativeMatrixBlue = new double[ nCols * nRows ];
71  yDerivativeMatrix( nCols, nRows, yDerivativeMatrixBlue, blueMatrix );
72  double *yDerivativeMatrixAlpha = new double[ nCols * nRows ];
73  yDerivativeMatrix( nCols, nRows, yDerivativeMatrixAlpha, alphaMatrix );
74 
75  //compute output
76  double nSrcPerDstX = ( double ) srcImage.width() / ( double ) dstImage.width();
77  double nSrcPerDstY = ( double ) srcImage.height() / ( double ) dstImage.height();
78 
79  double currentSrcRow = nSrcPerDstY / 2.0 - 0.5;
80  double currentSrcCol;
81  int currentSrcColInt;
82  int currentSrcRowInt;
83  int lastSrcColInt = -100;
84  int lastSrcRowInt = -100;
85 
86  //bernstein polynomials
87  double bp0u, bp1u, bp2u, bp3u, bp0v, bp1v, bp2v, bp3v;
88  double u, v;
89 
90  for ( int y = 0; y < dstImage.height(); ++y )
91  {
92  currentSrcRowInt = std::floor( currentSrcRow );
93  v = currentSrcRow - currentSrcRowInt;
94 
95  currentSrcCol = nSrcPerDstX / 2.0 - 0.5;
96 
97  QRgb *scanLine = ( QRgb * )dstImage.scanLine( y );
98  for ( int x = 0; x < dstImage.width(); ++x )
99  {
100  currentSrcColInt = std::floor( currentSrcCol );
101  u = currentSrcCol - currentSrcColInt;
102 
103  //handle eight edge-cases
104  if ( ( currentSrcRowInt < 0 || currentSrcRowInt >= ( srcImage.height() - 1 ) || currentSrcColInt < 0 || currentSrcColInt >= ( srcImage.width() - 1 ) ) )
105  {
106  QRgb px1, px2;
107  //pixels at the border of the source image needs to be handled in a special way
108  if ( currentSrcRowInt < 0 && currentSrcColInt < 0 )
109  {
110  scanLine[x] = srcImage.pixel( 0, 0 );
111  }
112  else if ( currentSrcRowInt < 0 && currentSrcColInt >= ( srcImage.width() - 1 ) )
113  {
114  scanLine[x] = srcImage.pixel( srcImage.width() - 1, 0 );
115  }
116  else if ( currentSrcRowInt >= ( srcImage.height() - 1 ) && currentSrcColInt >= ( srcImage.width() - 1 ) )
117  {
118  scanLine[x] = srcImage.pixel( srcImage.width() - 1, srcImage.height() - 1 );
119  }
120  else if ( currentSrcRowInt >= ( srcImage.height() - 1 ) && currentSrcColInt < 0 )
121  {
122  scanLine[x] = srcImage.pixel( 0, srcImage.height() - 1 );
123  }
124  else if ( currentSrcRowInt < 0 )
125  {
126  px1 = srcImage.pixel( currentSrcColInt, 0 );
127  px2 = srcImage.pixel( currentSrcColInt + 1, 0 );
128  scanLine[x] = curveInterpolation( px1, px2, u, xDerivativeMatrixRed[ currentSrcColInt ], xDerivativeMatrixGreen[ currentSrcColInt ],
129  xDerivativeMatrixBlue[ currentSrcColInt ], xDerivativeMatrixAlpha[ currentSrcColInt ], xDerivativeMatrixRed[ currentSrcColInt + 1 ], xDerivativeMatrixGreen[ currentSrcColInt + 1 ],
130  xDerivativeMatrixBlue[ currentSrcColInt + 1 ], xDerivativeMatrixAlpha[ currentSrcColInt + 1 ] );
131  }
132  else if ( currentSrcRowInt >= ( srcImage.height() - 1 ) )
133  {
134  int idx = ( srcImage.height() - 1 ) * srcImage.width() + currentSrcColInt;
135  px1 = srcImage.pixel( currentSrcColInt, srcImage.height() - 1 );
136  px2 = srcImage.pixel( currentSrcColInt + 1, srcImage.height() - 1 );
137  scanLine[x] = curveInterpolation( px1, px2, u, xDerivativeMatrixRed[ idx ], xDerivativeMatrixGreen[ idx ], xDerivativeMatrixBlue[idx],
138  xDerivativeMatrixAlpha[idx], xDerivativeMatrixRed[ idx + 1 ], xDerivativeMatrixGreen[ idx + 1 ], xDerivativeMatrixBlue[idx + 1],
139  xDerivativeMatrixAlpha[idx + 1] );
140  }
141  else if ( currentSrcColInt < 0 )
142  {
143  int idx1 = currentSrcRowInt * srcImage.width();
144  int idx2 = idx1 + srcImage.width();
145  px1 = srcImage.pixel( 0, currentSrcRowInt );
146  px2 = srcImage.pixel( 0, currentSrcRowInt + 1 );
147  scanLine[x] = curveInterpolation( px1, px2, v, yDerivativeMatrixRed[ idx1 ], yDerivativeMatrixGreen[ idx1 ], yDerivativeMatrixBlue[ idx1],
148  yDerivativeMatrixAlpha[ idx1], yDerivativeMatrixRed[ idx2 ], yDerivativeMatrixGreen[ idx2 ], yDerivativeMatrixBlue[ idx2],
149  yDerivativeMatrixAlpha[ idx2] );
150  }
151  else if ( currentSrcColInt >= ( srcImage.width() - 1 ) )
152  {
153  int idx1 = currentSrcRowInt * srcImage.width() + srcImage.width() - 1;
154  int idx2 = idx1 + srcImage.width();
155  px1 = srcImage.pixel( srcImage.width() - 1, currentSrcRowInt );
156  px2 = srcImage.pixel( srcImage.width() - 1, currentSrcRowInt + 1 );
157  scanLine[x] = curveInterpolation( px1, px2, v, yDerivativeMatrixRed[ idx1 ], yDerivativeMatrixGreen[ idx1 ], yDerivativeMatrixBlue[ idx1],
158  yDerivativeMatrixAlpha[ idx1], yDerivativeMatrixRed[ idx2 ], yDerivativeMatrixGreen[ idx2 ], yDerivativeMatrixBlue[ idx2],
159  yDerivativeMatrixAlpha[ idx2] );
160  }
161  currentSrcCol += nSrcPerDstX;
162  continue;
163  }
164 
165  //first update the control points if necessary
166  if ( currentSrcColInt != lastSrcColInt || currentSrcRowInt != lastSrcRowInt )
167  {
168  calculateControlPoints( nCols, nRows, currentSrcRowInt, currentSrcColInt, redMatrix, greenMatrix, blueMatrix, alphaMatrix,
169  xDerivativeMatrixRed, xDerivativeMatrixGreen, xDerivativeMatrixBlue, xDerivativeMatrixAlpha,
170  yDerivativeMatrixRed, yDerivativeMatrixGreen, yDerivativeMatrixBlue, yDerivativeMatrixAlpha );
171  }
172 
173  //bernstein polynomials
174  bp0u = calcBernsteinPolyN3( 0, u );
175  bp1u = calcBernsteinPolyN3( 1, u );
176  bp2u = calcBernsteinPolyN3( 2, u );
177  bp3u = calcBernsteinPolyN3( 3, u );
178  bp0v = calcBernsteinPolyN3( 0, v );
179  bp1v = calcBernsteinPolyN3( 1, v );
180  bp2v = calcBernsteinPolyN3( 2, v );
181  bp3v = calcBernsteinPolyN3( 3, v );
182 
183  //then calculate value based on bernstein form of Bezier patch
184  //todo: move into function
185  int r = bp0u * bp0v * cRed00 +
186  bp1u * bp0v * cRed10 +
187  bp2u * bp0v * cRed20 +
188  bp3u * bp0v * cRed30 +
189  bp0u * bp1v * cRed01 +
190  bp1u * bp1v * cRed11 +
191  bp2u * bp1v * cRed21 +
192  bp3u * bp1v * cRed31 +
193  bp0u * bp2v * cRed02 +
194  bp1u * bp2v * cRed12 +
195  bp2u * bp2v * cRed22 +
196  bp3u * bp2v * cRed32 +
197  bp0u * bp3v * cRed03 +
198  bp1u * bp3v * cRed13 +
199  bp2u * bp3v * cRed23 +
200  bp3u * bp3v * cRed33;
201 
202  int g = bp0u * bp0v * cGreen00 +
203  bp1u * bp0v * cGreen10 +
204  bp2u * bp0v * cGreen20 +
205  bp3u * bp0v * cGreen30 +
206  bp0u * bp1v * cGreen01 +
207  bp1u * bp1v * cGreen11 +
208  bp2u * bp1v * cGreen21 +
209  bp3u * bp1v * cGreen31 +
210  bp0u * bp2v * cGreen02 +
211  bp1u * bp2v * cGreen12 +
212  bp2u * bp2v * cGreen22 +
213  bp3u * bp2v * cGreen32 +
214  bp0u * bp3v * cGreen03 +
215  bp1u * bp3v * cGreen13 +
216  bp2u * bp3v * cGreen23 +
217  bp3u * bp3v * cGreen33;
218 
219  int b = bp0u * bp0v * cBlue00 +
220  bp1u * bp0v * cBlue10 +
221  bp2u * bp0v * cBlue20 +
222  bp3u * bp0v * cBlue30 +
223  bp0u * bp1v * cBlue01 +
224  bp1u * bp1v * cBlue11 +
225  bp2u * bp1v * cBlue21 +
226  bp3u * bp1v * cBlue31 +
227  bp0u * bp2v * cBlue02 +
228  bp1u * bp2v * cBlue12 +
229  bp2u * bp2v * cBlue22 +
230  bp3u * bp2v * cBlue32 +
231  bp0u * bp3v * cBlue03 +
232  bp1u * bp3v * cBlue13 +
233  bp2u * bp3v * cBlue23 +
234  bp3u * bp3v * cBlue33;
235 
236  int a = bp0u * bp0v * cAlpha00 +
237  bp1u * bp0v * cAlpha10 +
238  bp2u * bp0v * cAlpha20 +
239  bp3u * bp0v * cAlpha30 +
240  bp0u * bp1v * cAlpha01 +
241  bp1u * bp1v * cAlpha11 +
242  bp2u * bp1v * cAlpha21 +
243  bp3u * bp1v * cAlpha31 +
244  bp0u * bp2v * cAlpha02 +
245  bp1u * bp2v * cAlpha12 +
246  bp2u * bp2v * cAlpha22 +
247  bp3u * bp2v * cAlpha32 +
248  bp0u * bp3v * cAlpha03 +
249  bp1u * bp3v * cAlpha13 +
250  bp2u * bp3v * cAlpha23 +
251  bp3u * bp3v * cAlpha33;
252 
253  scanLine[x] = createPremultipliedColor( r, g, b, a );
254 
255  lastSrcColInt = currentSrcColInt;
256  currentSrcCol += nSrcPerDstX;
257  }
258  lastSrcRowInt = currentSrcRowInt;
259  currentSrcRow += nSrcPerDstY;
260  }
261 
262 
263  //cleanup memory
264  delete[] redMatrix;
265  delete[] greenMatrix;
266  delete[] blueMatrix;
267  delete[] alphaMatrix;
268  delete[] xDerivativeMatrixRed;
269  delete[] xDerivativeMatrixGreen;
270  delete[] xDerivativeMatrixBlue;
271  delete[] xDerivativeMatrixAlpha;
272  delete[] yDerivativeMatrixRed;
273  delete[] yDerivativeMatrixGreen;
274  delete[] yDerivativeMatrixBlue;
275  delete[] yDerivativeMatrixAlpha;
276 }
277 
278 void QgsCubicRasterResampler::xDerivativeMatrix( int nCols, int nRows, double *matrix, const int *colorMatrix )
279 {
280  double val = 0;
281  int index = 0;
282 
283  for ( int y = 0; y < nRows; ++y )
284  {
285  for ( int x = 0; x < nCols; ++x )
286  {
287  if ( x == 0 )
288  {
289  val = colorMatrix[index + 1] - colorMatrix[index];
290  }
291  else if ( x == ( nCols - 1 ) )
292  {
293  val = colorMatrix[index] - colorMatrix[ index - 1 ];
294  }
295  else
296  {
297  val = ( colorMatrix[index + 1] - colorMatrix[index - 1] ) / 2.0;
298  }
299  matrix[index] = val;
300  ++index;
301  }
302  }
303 }
304 
305 void QgsCubicRasterResampler::yDerivativeMatrix( int nCols, int nRows, double *matrix, const int *colorMatrix )
306 {
307  double val = 0;
308  int index = 0;
309 
310  for ( int y = 0; y < nRows; ++y )
311  {
312  for ( int x = 0; x < nCols; ++x )
313  {
314  if ( y == 0 )
315  {
316  val = colorMatrix[ index + nCols ] - colorMatrix[ index ];
317  }
318  else if ( y == ( nRows - 1 ) )
319  {
320  val = colorMatrix[ index ] - colorMatrix[ index - nCols ];
321  }
322  else
323  {
324  val = ( colorMatrix[ index + nCols ] - colorMatrix[ index - nCols ] ) / 2.0;
325  }
326  matrix[index] = val;
327  ++index;
328  }
329  }
330 }
331 
332 void QgsCubicRasterResampler::calculateControlPoints( int nCols, int nRows, int currentRow, int currentCol, int *redMatrix, int *greenMatrix, int *blueMatrix,
333  int *alphaMatrix, double *xDerivativeMatrixRed, double *xDerivativeMatrixGreen, double *xDerivativeMatrixBlue, double *xDerivativeMatrixAlpha,
334  double *yDerivativeMatrixRed, double *yDerivativeMatrixGreen, double *yDerivativeMatrixBlue, double *yDerivativeMatrixAlpha )
335 {
336  Q_UNUSED( nRows )
337  int idx00 = currentRow * nCols + currentCol;
338  int idx10 = idx00 + 1;
339  int idx01 = idx00 + nCols;
340  int idx11 = idx01 + 1;
341 
342  //corner points
343  cRed00 = redMatrix[idx00];
344  cGreen00 = greenMatrix[idx00];
345  cBlue00 = blueMatrix[idx00];
346  cAlpha00 = alphaMatrix[idx00];
347  cRed30 = redMatrix[idx10];
348  cGreen30 = greenMatrix[idx10];
349  cBlue30 = blueMatrix[idx10];
350  cAlpha30 = alphaMatrix[idx10];
351  cRed03 = redMatrix[idx01];
352  cGreen03 = greenMatrix[idx01];
353  cBlue03 = blueMatrix[idx01];
354  cAlpha03 = alphaMatrix[idx01];
355  cRed33 = redMatrix[idx11];
356  cGreen33 = greenMatrix[idx11];
357  cBlue33 = blueMatrix[idx11];
358  cAlpha33 = alphaMatrix[idx11];
359 
360  //control points near c00
361  cRed10 = cRed00 + 0.333 * xDerivativeMatrixRed[idx00];
362  cGreen10 = cGreen00 + 0.333 * xDerivativeMatrixGreen[idx00];
363  cBlue10 = cBlue00 + 0.333 * xDerivativeMatrixBlue[idx00];
364  cAlpha10 = cAlpha00 + 0.333 * xDerivativeMatrixAlpha[idx00];
365  cRed01 = cRed00 + 0.333 * yDerivativeMatrixRed[idx00];
366  cGreen01 = cGreen00 + 0.333 * yDerivativeMatrixGreen[idx00];
367  cBlue01 = cBlue00 + 0.333 * yDerivativeMatrixBlue[idx00];
368  cAlpha01 = cAlpha00 + 0.333 * yDerivativeMatrixAlpha[idx00];
369  cRed11 = cRed10 + 0.333 * yDerivativeMatrixRed[idx00];
370  cGreen11 = cGreen10 + 0.333 * yDerivativeMatrixGreen[idx00];
371  cBlue11 = cBlue10 + 0.333 * yDerivativeMatrixBlue[idx00];
372  cAlpha11 = cAlpha10 + 0.333 * yDerivativeMatrixAlpha[idx00];
373 
374  //control points near c30
375  cRed20 = cRed30 - 0.333 * xDerivativeMatrixRed[idx10];
376  cGreen20 = cGreen30 - 0.333 * xDerivativeMatrixGreen[idx10];
377  cBlue20 = cBlue30 - 0.333 * xDerivativeMatrixBlue[idx10];
378  cAlpha20 = cAlpha30 - 0.333 * xDerivativeMatrixAlpha[idx10];
379  cRed31 = cRed30 + 0.333 * yDerivativeMatrixRed[idx10];
380  cGreen31 = cGreen30 + 0.333 * yDerivativeMatrixGreen[idx10];
381  cBlue31 = cBlue30 + 0.333 * yDerivativeMatrixBlue[idx10];
382  cAlpha31 = cAlpha30 + 0.333 * yDerivativeMatrixAlpha[idx10];
383  cRed21 = cRed20 + 0.333 * yDerivativeMatrixRed[idx10];
384  cGreen21 = cGreen20 + 0.333 * yDerivativeMatrixGreen[idx10];
385  cBlue21 = cBlue20 + 0.333 * yDerivativeMatrixBlue[idx10];
386  cAlpha21 = cAlpha20 + 0.333 * yDerivativeMatrixAlpha[idx10];
387 
388  //control points near c03
389  cRed13 = cRed03 + 0.333 * xDerivativeMatrixRed[idx01];
390  cGreen13 = cGreen03 + 0.333 * xDerivativeMatrixGreen[idx01];
391  cBlue13 = cBlue03 + 0.333 * xDerivativeMatrixBlue[idx01];
392  cAlpha13 = cAlpha03 + 0.333 * xDerivativeMatrixAlpha[idx01];
393  cRed02 = cRed03 - 0.333 * yDerivativeMatrixRed[idx01];
394  cGreen02 = cGreen03 - 0.333 * yDerivativeMatrixGreen[idx01];
395  cBlue02 = cBlue03 - 0.333 * yDerivativeMatrixBlue[idx01];
396  cAlpha02 = cAlpha03 - 0.333 * yDerivativeMatrixAlpha[idx01];
397  cRed12 = cRed02 + 0.333 * xDerivativeMatrixRed[idx01];
398  cGreen12 = cGreen02 + 0.333 * xDerivativeMatrixGreen[idx01];
399  cBlue12 = cBlue02 + 0.333 * xDerivativeMatrixBlue[idx01];
400  cAlpha12 = cAlpha02 + 0.333 * xDerivativeMatrixAlpha[idx01];
401 
402  //control points near c33
403  cRed23 = cRed33 - 0.333 * xDerivativeMatrixRed[idx11];
404  cGreen23 = cGreen33 - 0.333 * xDerivativeMatrixGreen[idx11];
405  cBlue23 = cBlue33 - 0.333 * xDerivativeMatrixBlue[idx11];
406  cAlpha23 = cAlpha33 - 0.333 * xDerivativeMatrixAlpha[idx11];
407  cRed32 = cRed33 - 0.333 * yDerivativeMatrixRed[idx11];
408  cGreen32 = cGreen33 - 0.333 * yDerivativeMatrixGreen[idx11];
409  cBlue32 = cBlue33 - 0.333 * yDerivativeMatrixBlue[idx11];
410  cAlpha32 = cAlpha33 - 0.333 * yDerivativeMatrixAlpha[idx11];
411  cRed22 = cRed32 - 0.333 * xDerivativeMatrixRed[idx11];
412  cGreen22 = cGreen32 - 0.333 * xDerivativeMatrixGreen[idx11];
413  cBlue22 = cBlue32 - 0.333 * xDerivativeMatrixBlue[idx11];
414  cAlpha22 = cAlpha32 - 0.333 * xDerivativeMatrixAlpha[idx11];
415 }
416 
417 QRgb QgsCubicRasterResampler::curveInterpolation( QRgb pt1, QRgb pt2, double t, double d1red, double d1green, double d1blue, double d1alpha,
418  double d2red, double d2green, double d2blue, double d2alpha )
419 {
420  //control points
421  double p0r = qRed( pt1 );
422  double p1r = p0r + 0.333 * d1red;
423  double p3r = qRed( pt2 );
424  double p2r = p3r - 0.333 * d2red;
425  double p0g = qGreen( pt1 );
426  double p1g = p0g + 0.333 * d1green;
427  double p3g = qGreen( pt2 );
428  double p2g = p3g - 0.333 * d2green;
429  double p0b = qBlue( pt1 );
430  double p1b = p0b + 0.333 * d1blue;
431  double p3b = qBlue( pt2 );
432  double p2b = p3b - 0.333 * d2blue;
433  double p0a = qAlpha( pt1 );
434  double p1a = p0a + 0.333 * d1alpha;
435  double p3a = qAlpha( pt2 );
436  double p2a = p3a - 0.333 * d2alpha;
437 
438  //bernstein polynomials
439  double bp0 = calcBernsteinPolyN3( 0, t );
440  double bp1 = calcBernsteinPolyN3( 1, t );
441  double bp2 = calcBernsteinPolyN3( 2, t );
442  double bp3 = calcBernsteinPolyN3( 3, t );
443 
444  int red = bp0 * p0r + bp1 * p1r + bp2 * p2r + bp3 * p3r;
445  int green = bp0 * p0g + bp1 * p1g + bp2 * p2g + bp3 * p3g;
446  int blue = bp0 * p0b + bp1 * p1b + bp2 * p2b + bp3 * p3b;
447  int alpha = bp0 * p0a + bp1 * p1a + bp2 * p2a + bp3 * p3a;
448 
449  return createPremultipliedColor( red, green, blue, alpha );
450 }
451 
452 double QgsCubicRasterResampler::calcBernsteinPolyN3( int i, double t )
453 {
454  if ( i < 0 )
455  {
456  return 0;
457  }
458 
459  return lowerN3( i ) * std::pow( t, i ) * std::pow( ( 1 - t ), ( 3 - i ) );
460 }
461 
462 inline int QgsCubicRasterResampler::lowerN3( int i )
463 {
464  switch ( i )
465  {
466  case 0:
467  case 3:
468  return 1;
469  case 1:
470  case 2:
471  return 3;
472  default:
473  return 0;
474  }
475 }
476 
477 QRgb QgsCubicRasterResampler::createPremultipliedColor( const int r, const int g, const int b, const int a )
478 {
479  int maxComponentBounds = qBound( 0, a, 255 );
480  return qRgba( qBound( 0, r, maxComponentBounds ),
481  qBound( 0, g, maxComponentBounds ),
482  qBound( 0, b, maxComponentBounds ),
483  a );
484 }
Cubic Raster Resampler.
QgsCubicRasterResampler * clone() const override
Gets a deep copy of this object.
void resample(const QImage &srcImage, QImage &dstImage) override
QgsCubicRasterResampler()=default
Constructor for QgsCubicRasterResampler.