29 int nCols = srcImage.width();
30 int nRows = srcImage.height();
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 ];
39 for (
int heightIndex = 0; heightIndex < nRows; ++heightIndex )
41 QRgb *scanLine = ( QRgb * )srcImage.constScanLine( heightIndex );
42 for (
int widthIndex = 0; widthIndex < nCols; ++widthIndex )
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 );
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 );
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 );
76 double nSrcPerDstX = ( double ) srcImage.width() / ( double ) dstImage.width();
77 double nSrcPerDstY = ( double ) srcImage.height() / ( double ) dstImage.height();
79 double currentSrcRow = nSrcPerDstY / 2.0 - 0.5;
83 int lastSrcColInt = -100;
84 int lastSrcRowInt = -100;
87 double bp0u, bp1u, bp2u, bp3u, bp0v, bp1v, bp2v, bp3v;
90 for (
int y = 0; y < dstImage.height(); ++y )
92 currentSrcRowInt = std::floor( currentSrcRow );
93 v = currentSrcRow - currentSrcRowInt;
95 currentSrcCol = nSrcPerDstX / 2.0 - 0.5;
97 QRgb *scanLine = ( QRgb * )dstImage.scanLine( y );
98 for (
int x = 0; x < dstImage.width(); ++x )
100 currentSrcColInt = std::floor( currentSrcCol );
101 u = currentSrcCol - currentSrcColInt;
104 if ( ( currentSrcRowInt < 0 || currentSrcRowInt >= ( srcImage.height() - 1 ) || currentSrcColInt < 0 || currentSrcColInt >= ( srcImage.width() - 1 ) ) )
108 if ( currentSrcRowInt < 0 && currentSrcColInt < 0 )
110 scanLine[x] = srcImage.pixel( 0, 0 );
112 else if ( currentSrcRowInt < 0 && currentSrcColInt >= ( srcImage.width() - 1 ) )
114 scanLine[x] = srcImage.pixel( srcImage.width() - 1, 0 );
116 else if ( currentSrcRowInt >= ( srcImage.height() - 1 ) && currentSrcColInt >= ( srcImage.width() - 1 ) )
118 scanLine[x] = srcImage.pixel( srcImage.width() - 1, srcImage.height() - 1 );
120 else if ( currentSrcRowInt >= ( srcImage.height() - 1 ) && currentSrcColInt < 0 )
122 scanLine[x] = srcImage.pixel( 0, srcImage.height() - 1 );
124 else if ( currentSrcRowInt < 0 )
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 ] );
132 else if ( currentSrcRowInt >= ( srcImage.height() - 1 ) )
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] );
141 else if ( currentSrcColInt < 0 )
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] );
151 else if ( currentSrcColInt >= ( srcImage.width() - 1 ) )
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] );
161 currentSrcCol += nSrcPerDstX;
166 if ( currentSrcColInt != lastSrcColInt || currentSrcRowInt != lastSrcRowInt )
168 calculateControlPoints( nCols, nRows, currentSrcRowInt, currentSrcColInt, redMatrix, greenMatrix, blueMatrix, alphaMatrix,
169 xDerivativeMatrixRed, xDerivativeMatrixGreen, xDerivativeMatrixBlue, xDerivativeMatrixAlpha,
170 yDerivativeMatrixRed, yDerivativeMatrixGreen, yDerivativeMatrixBlue, yDerivativeMatrixAlpha );
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 );
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;
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;
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;
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;
253 scanLine[x] = createPremultipliedColor( r, g, b, a );
255 lastSrcColInt = currentSrcColInt;
256 currentSrcCol += nSrcPerDstX;
258 lastSrcRowInt = currentSrcRowInt;
259 currentSrcRow += nSrcPerDstY;
265 delete[] greenMatrix;
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;
278 void QgsCubicRasterResampler::xDerivativeMatrix(
int nCols,
int nRows,
double *matrix,
const int *colorMatrix )
283 for (
int y = 0; y < nRows; ++y )
285 for (
int x = 0; x < nCols; ++x )
289 val = colorMatrix[index + 1] - colorMatrix[index];
291 else if ( x == ( nCols - 1 ) )
293 val = colorMatrix[index] - colorMatrix[ index - 1 ];
297 val = ( colorMatrix[index + 1] - colorMatrix[index - 1] ) / 2.0;
305 void QgsCubicRasterResampler::yDerivativeMatrix(
int nCols,
int nRows,
double *matrix,
const int *colorMatrix )
310 for (
int y = 0; y < nRows; ++y )
312 for (
int x = 0; x < nCols; ++x )
316 val = colorMatrix[ index + nCols ] - colorMatrix[ index ];
318 else if ( y == ( nRows - 1 ) )
320 val = colorMatrix[ index ] - colorMatrix[ index - nCols ];
324 val = ( colorMatrix[ index + nCols ] - colorMatrix[ index - nCols ] ) / 2.0;
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 )
337 int idx00 = currentRow * nCols + currentCol;
338 int idx10 = idx00 + 1;
339 int idx01 = idx00 + nCols;
340 int idx11 = idx01 + 1;
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];
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];
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];
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];
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];
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 )
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;
439 double bp0 = calcBernsteinPolyN3( 0, t );
440 double bp1 = calcBernsteinPolyN3( 1, t );
441 double bp2 = calcBernsteinPolyN3( 2, t );
442 double bp3 = calcBernsteinPolyN3( 3, t );
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;
449 return createPremultipliedColor( red, green, blue, alpha );
452 double QgsCubicRasterResampler::calcBernsteinPolyN3(
int i,
double t )
459 return lowerN3( i ) * std::pow( t, i ) * std::pow( ( 1 - t ), ( 3 - i ) );
462 inline int QgsCubicRasterResampler::lowerN3(
int i )
477 QRgb QgsCubicRasterResampler::createPremultipliedColor(
const int r,
const int g,
const int b,
const int a )
479 int maxComponentBounds = qBound( 0, a, 255 );
480 return qRgba( qBound( 0, r, maxComponentBounds ),
481 qBound( 0, g, maxComponentBounds ),
482 qBound( 0, b, maxComponentBounds ),
QgsCubicRasterResampler * clone() const override
Gets a deep copy of this object.
void resample(const QImage &srcImage, QImage &dstImage) override
QgsCubicRasterResampler()=default
Constructor for QgsCubicRasterResampler.