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