Skip to content

Commit 3d0b85a

Browse files
committed
Added cubic resampler (not working yet)
1 parent e9b8cc0 commit 3d0b85a

File tree

6 files changed

+289
-30
lines changed

6 files changed

+289
-30
lines changed

src/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ SET(QGIS_CORE_SRCS
166166

167167
raster/qgsrasterrenderer.cpp
168168
raster/qgsbilinearrasterresampler.cpp
169+
raster/qgscubicrasterresampler.cpp
169170
raster/qgspalettedrasterrenderer.cpp
170171
raster/qgsmultibandcolorrenderer.cpp
171172

src/core/raster/qgsbilinearrasterresampler.cpp

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -43,27 +43,33 @@ void QgsBilinearRasterResampler::resample( const QImage& srcImage, QImage& dstIm
4343
{
4444
currentSrcRow += nSrcPerDstY;
4545
}
46-
else if ( currentSrcRow > srcImage.height() - 2 )
47-
{
48-
//todo: resample in one direction only
49-
break;
50-
}
5146

5247
currentSrcCol = nSrcPerDstY / 2.0 - 0.5;
5348
for ( int j = 0; j < dstImage.width(); ++j )
5449
{
50+
double u = currentSrcCol - ( int )currentSrcCol;
51+
double v = currentSrcRow - ( int )currentSrcRow;
5552
if ( currentSrcCol > srcImage.width() - 2 )
5653
{
57-
//todo: resample in one direction only
54+
//resample in one direction only
55+
px1 = srcImage.pixel( currentSrcCol, currentSrcRow );
56+
px2 = srcImage.pixel( currentSrcCol, currentSrcRow + 1 );
57+
dstImage.setPixel( j, i, resampleColorValue( v, px1, px2 ) );
58+
currentSrcCol += nSrcPerDstX;
59+
continue;
60+
}
61+
else if ( currentSrcRow > srcImage.height() - 2 )
62+
{
63+
px1 = srcImage.pixel( currentSrcCol, currentSrcRow );
64+
px2 = srcImage.pixel( currentSrcCol + 1, currentSrcRow );
65+
dstImage.setPixel( j, i, resampleColorValue( u, px1, px2 ) );
5866
currentSrcCol += nSrcPerDstX;
5967
continue;
6068
}
6169
px1 = srcImage.pixel( currentSrcCol, currentSrcRow );
6270
px2 = srcImage.pixel( currentSrcCol + 1, currentSrcRow );
6371
px3 = srcImage.pixel( currentSrcCol + 1, currentSrcRow + 1 );
6472
px4 = srcImage.pixel( currentSrcCol, currentSrcRow + 1 );
65-
double u = currentSrcCol - ( int )currentSrcCol;
66-
double v = currentSrcRow - ( int )currentSrcRow;
6773
dstImage.setPixel( j, i, resampleColorValue( u, v, px1, px2, px3, px4 ) );
6874
currentSrcCol += nSrcPerDstX;
6975
}
@@ -73,26 +79,13 @@ void QgsBilinearRasterResampler::resample( const QImage& srcImage, QImage& dstIm
7379

7480
QRgb QgsBilinearRasterResampler::resampleColorValue( double u, double v, QRgb col1, QRgb col2, QRgb col3, QRgb col4 ) const
7581
{
76-
double r1 = qRed( col1 );
77-
double g1 = qGreen( col1 );
78-
double b1 = qBlue( col1 );
79-
double r2 = qRed( col2 );
80-
double g2 = qGreen( col2 );
81-
double b2 = qBlue( col2 );
82-
double r3 = qRed( col3 );
83-
double g3 = qGreen( col3 );
84-
double b3 = qBlue( col3 );
85-
double r4 = qRed( col4 );
86-
double g4 = qGreen( col4 );
87-
double b4 = qBlue( col4 );
88-
89-
double rt1 = u * r2 + ( 1 - u ) * r1;
90-
double gt1 = u * g2 + ( 1 - u ) * g1;
91-
double bt1 = u * b2 + ( 1 - u ) * b1;
92-
93-
double rt2 = u * r3 + ( 1 - u ) * r4;
94-
double gt2 = u * g3 + ( 1 - u ) * g4;
95-
double bt2 = u * b3 + ( 1 - u ) * b4;
82+
int red = bilinearInterpolation( u, v, qRed( col1 ), qRed( col2 ), qRed( col3 ), qRed( col4 ) );
83+
int green = bilinearInterpolation( u, v, qGreen( col1 ), qGreen( col2 ), qGreen( col3 ), qGreen( col4 ) );
84+
int blue = bilinearInterpolation( u, v, qBlue( col1 ), qBlue( col2 ), qBlue( col3 ), qBlue( col4 ) );
85+
return qRgb( red, green, blue );
86+
}
9687

97-
return qRgb( v * rt2 + ( 1 - v ) * rt1, v * gt2 + ( 1 - v ) * gt1, v * bt2 + ( 1 - v ) * bt1 );
88+
QRgb QgsBilinearRasterResampler::resampleColorValue( double u, QRgb col1, QRgb col2 ) const
89+
{
90+
return qRgb( qRed( col1 ) * ( 1 - u ) + qRed( col2 ) * u, qGreen( col1 ) * ( 1 - u ) + qGreen( col2 ) * u, qBlue( col1 ) * ( 1 - u ) + qBlue( col2 ) * u );
9891
}

src/core/raster/qgsbilinearrasterresampler.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ class QgsBilinearRasterResampler: public QgsRasterResampler
3131

3232
private:
3333
QRgb resampleColorValue( double u, double v, QRgb col1, QRgb col2, QRgb col3, QRgb col4 ) const;
34+
QRgb resampleColorValue( double u, QRgb col1, QRgb col2 ) const;
35+
inline double bilinearInterpolation( double u, double v, int val1, int val2, int val3, int val4 ) const;
3436
};
3537

38+
double QgsBilinearRasterResampler::bilinearInterpolation( double u, double v, int val1, int val2, int val3, int val4 ) const
39+
{
40+
return ( val1 * ( 1 - u ) * ( 1 - v ) + val2 * ( 1 - v ) * u + val4 * ( 1 - u ) * v + val3 * u * v );
41+
}
42+
3643
#endif // QGSBILINEARRASTERRESAMPLER_H
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
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+
18+
#include "qgscubicrasterresampler.h"
19+
#include <QImage>
20+
21+
QgsCubicRasterResampler::QgsCubicRasterResampler()
22+
{
23+
}
24+
25+
QgsCubicRasterResampler::~QgsCubicRasterResampler()
26+
{
27+
}
28+
29+
void QgsCubicRasterResampler::resample( const QImage& srcImage, QImage& dstImage ) const
30+
{
31+
int nCols = srcImage.width();
32+
int nRows = srcImage.height();
33+
34+
int pos = 0;
35+
QRgb px;
36+
int* redMatrix = new int[ nCols * nRows ];
37+
int* greenMatrix = new int[ nCols * nRows ];
38+
int* blueMatrix = new int[ nCols * nRows ];
39+
40+
for( int i = 0; i < nRows; ++i )
41+
{
42+
for( int j = 0; j < nCols; ++j )
43+
{
44+
px = srcImage.pixel( j, i );
45+
redMatrix[pos] = qRed( px );
46+
greenMatrix[pos] = qGreen( px );
47+
blueMatrix[pos] = qBlue( px );
48+
++pos;
49+
}
50+
}
51+
52+
//derivative x
53+
double* xDerivativeMatrixRed = new double[ nCols * nRows ];
54+
xDerivativeMatrix( nCols, nRows, xDerivativeMatrixRed, redMatrix );
55+
double* xDerivativeMatrixGreen = new double[ nCols * nRows ];
56+
xDerivativeMatrix( nCols, nRows, xDerivativeMatrixGreen, greenMatrix );
57+
double* xDerivativeMatrixBlue = new double[ nCols * nRows ];
58+
xDerivativeMatrix( nCols, nRows, xDerivativeMatrixBlue, blueMatrix );
59+
60+
//derivative y
61+
double* yDerivativeMatrixRed = new double[ nCols * nRows ];
62+
yDerivativeMatrix<int>( nCols, nRows, yDerivativeMatrixRed, redMatrix );
63+
double* yDerivativeMatrixGreen = new double[ nCols * nRows ];
64+
yDerivativeMatrix<int>( nCols, nRows, yDerivativeMatrixGreen, greenMatrix );
65+
double* yDerivativeMatrixBlue = new double[ nCols * nRows ];
66+
yDerivativeMatrix<int>( nCols, nRows, yDerivativeMatrixBlue, blueMatrix );
67+
68+
//derivative xy
69+
double* xyDerivativeMatrixRed = new double[ nCols * nRows ];
70+
yDerivativeMatrix<double>( nCols, nRows, xyDerivativeMatrixRed, xDerivativeMatrixRed );
71+
double* xyDerivativeMatrixGreen = new double[ nCols * nRows ];
72+
yDerivativeMatrix<double>( nCols, nRows, xyDerivativeMatrixGreen, xDerivativeMatrixGreen );
73+
double* xyDerivativeMatrixBlue = new double[ nCols * nRows ];
74+
yDerivativeMatrix<double>( nCols, nRows, xyDerivativeMatrixBlue, xDerivativeMatrixBlue );
75+
76+
//compute output
77+
double nSrcPerDstX = ( double ) srcImage.width() / ( double ) dstImage.width();
78+
double nSrcPerDstY = ( double ) srcImage.height() / ( double ) dstImage.height();
79+
80+
double currentSrcRow = nSrcPerDstX / 2.0 - 0.5;
81+
double currentSrcCol;
82+
int currentSrcColInt;
83+
int currentSrcRowInt;
84+
85+
int r, g, b;
86+
int index;
87+
88+
for ( int i = 0; i < dstImage.height(); ++i )
89+
{
90+
currentSrcRowInt = (int) currentSrcRow;
91+
92+
currentSrcCol = nSrcPerDstY / 2.0 - 0.5;
93+
for( int j = 0; j < dstImage.width(); ++j )
94+
{
95+
//out of bounds check
96+
currentSrcColInt = (int)currentSrcCol;
97+
if( currentSrcColInt < 0 || currentSrcColInt > srcImage.width() - 2
98+
|| currentSrcRowInt < 0 || currentSrcRowInt > srcImage.height() - 2 )
99+
{
100+
currentSrcCol += nSrcPerDstX;
101+
++index;
102+
dstImage.setPixel( j, i, qRgb( 0, 0, 255 ) );
103+
continue;
104+
}
105+
106+
107+
//interpolation
108+
index = currentSrcRowInt * nCols + currentSrcColInt;
109+
r = cubicInterpolation( redMatrix[index], redMatrix[index + 1], redMatrix[index + nCols + 1 ], redMatrix[ index + nCols ],
110+
xDerivativeMatrixRed[index], xDerivativeMatrixRed[index + 1], xDerivativeMatrixRed[index + nCols + 1 ], xDerivativeMatrixRed[ index + nCols ],
111+
yDerivativeMatrixRed[index], yDerivativeMatrixRed[index + 1], yDerivativeMatrixRed[index + nCols + 1 ], yDerivativeMatrixRed[ index + nCols ],
112+
xyDerivativeMatrixRed[index], xyDerivativeMatrixRed[index + 1], xyDerivativeMatrixRed[index + nCols + 1 ], xyDerivativeMatrixRed[ index + nCols ] );
113+
g = cubicInterpolation( greenMatrix[index], greenMatrix[index + 1], greenMatrix[index + nCols + 1 ], greenMatrix[ index + nCols ],
114+
xDerivativeMatrixGreen[index], xDerivativeMatrixGreen[index + 1], xDerivativeMatrixGreen[index + nCols + 1 ], xDerivativeMatrixGreen[ index + nCols ],
115+
yDerivativeMatrixGreen[index], yDerivativeMatrixGreen[index + 1], yDerivativeMatrixGreen[index + nCols + 1 ], yDerivativeMatrixGreen[ index + nCols ],
116+
xyDerivativeMatrixGreen[index], xyDerivativeMatrixGreen[index + 1], xyDerivativeMatrixGreen[index + nCols + 1 ], xyDerivativeMatrixGreen[ index + nCols ] );
117+
b = cubicInterpolation( blueMatrix[index], blueMatrix[index + 1], blueMatrix[index + nCols + 1 ], blueMatrix[ index + nCols ],
118+
xDerivativeMatrixBlue[index], xDerivativeMatrixBlue[index + 1], xDerivativeMatrixBlue[index + nCols + 1 ], xDerivativeMatrixBlue[ index + nCols ],
119+
yDerivativeMatrixBlue[index], yDerivativeMatrixBlue[index + 1], yDerivativeMatrixBlue[index + nCols + 1 ], yDerivativeMatrixBlue[ index + nCols ],
120+
xyDerivativeMatrixBlue[index], xyDerivativeMatrixBlue[index + 1], xyDerivativeMatrixBlue[index + nCols + 1 ], xyDerivativeMatrixBlue[ index + nCols ] );
121+
122+
dstImage.setPixel( j, i, qRgb( 255, 0, 0 ) );
123+
currentSrcCol += nSrcPerDstX;
124+
}
125+
currentSrcRow += nSrcPerDstY;
126+
}
127+
128+
129+
//cleanup memory
130+
delete[] redMatrix;
131+
delete[] greenMatrix;
132+
delete[] blueMatrix;
133+
delete[] xDerivativeMatrixRed;
134+
delete[] xDerivativeMatrixGreen;
135+
delete[] xDerivativeMatrixBlue;
136+
delete[] yDerivativeMatrixRed;
137+
delete[] yDerivativeMatrixGreen;
138+
delete[] yDerivativeMatrixBlue;
139+
delete[] xyDerivativeMatrixRed;
140+
delete[] xyDerivativeMatrixGreen;
141+
delete[] xyDerivativeMatrixBlue;
142+
}
143+
144+
void QgsCubicRasterResampler::xDerivativeMatrix( int nCols, int nRows, double* matrix, const int* colorMatrix )
145+
{
146+
double val;
147+
int index = 0;
148+
149+
for( int i = 0; i < nRows; ++i )
150+
{
151+
for( int j = 0; j < nCols; ++j )
152+
{
153+
if( j < 1 )
154+
{
155+
val = colorMatrix[index + 1] - colorMatrix[index];
156+
}
157+
else if( j == ( nCols - 1 ) )
158+
{
159+
val = colorMatrix[index] - colorMatrix[ index - 1 ];
160+
}
161+
else
162+
{
163+
val = ( colorMatrix[index + 1] - colorMatrix[index - 1] ) / 2.0;
164+
}
165+
matrix[index] = val;
166+
++index;
167+
}
168+
}
169+
}
170+
171+
int QgsCubicRasterResampler::cubicInterpolation( double p1, double p2, double p3, double p4, double p1x, double p2x, double p3x, double p4x,
172+
double p1y, double p2y, double p3y, double p4y, double p1xy, double p2xy, double p3xy, double p4xy )
173+
{
174+
#if 0
175+
//calculate 16 coefficients
176+
double a00 = p1 - 3 * p4 + 2* p3 - 3 * p1y + 9 * p4y - 6 * p3y + 2 * p1xy - 6 * p4xy+ 4 * p3xy;
177+
double a10 = 3 * p4 - 2 * p3 - 9* p4y + 6 * p3y + 6 * p4xy - 4 * p3xy;
178+
double a20 = 3 * p1y - 9 * p4y + 6 * p3y - 2 * p1xy + 6 * p4xy - 4 * p3xy;
179+
double a30 = 9 * p4y - 6 * p3y - 6 * p4xy + 4 * p3xy;
180+
double a01 = p2 - 2 * p4 + p3 - 3 * p2y + 6 * p4y -3 * p3y + 2 * p2xy - 4 * p4xy + 2 * p3xy;
181+
double a11 = - p4 + p3 + 3 * p4y + -3 * p3y - 2 * p4xy;
182+
double a21 = 3 * p2y - 6 * p4y + 3 * p3y -2 * p2xy + 4 * p4xy - 2 * p3xy;
183+
double a31 = - 3 * p4y + 3 * p3y + 2 * p4xy -2 * p3xy;
184+
double a02 = p1x - 3 * p4x + 2 * p3x - 2 * p1y + 6 * p4y - 4 * p3y + p1xy - 3 * p4xy + 2 * p3xy;
185+
double a12 = 3 * p4x - 2 * p3x - 6 * p4y + 4 * p3y + 3 * p4xy - 2 * p3xy;
186+
double a22 = - p1y + 3 * p4y - 2 * p3y + p1xy - 3 * p4xy + 2 * p3xy;
187+
double a32 = -3 * p4y + 2 * p3y + 3 * p4xy - 2 * p3xy;
188+
double a03 = p2x - 2 * p4x + p3x - 2 * p4y + 4 * p4y - 2 * p3y + p2xy - 2 * p4xy + p3xy;
189+
double a13 = - p4x + p3x + 2 * p4y - 2 * p3y - p4xy + p3xy;
190+
#endif //0
191+
return 0;
192+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/***************************************************************************
2+
qgscubicrasterresampler.h
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+
18+
#ifndef QGSCUBICRASTERRESAMPLER_H
19+
#define QGSCUBICRASTERRESAMPLER_H
20+
21+
#include "qgsrasterresampler.h"
22+
23+
class QgsCubicRasterResampler: public QgsRasterResampler
24+
{
25+
public:
26+
QgsCubicRasterResampler();
27+
~QgsCubicRasterResampler();
28+
void resample( const QImage& srcImage, QImage& dstImage ) const;
29+
30+
private:
31+
static void xDerivativeMatrix( int nCols, int nRows, double* matrix, const int* colorMatrix );
32+
template <class T> void yDerivativeMatrix( int nCols, int nRows, double* dstMatrix, const T* srcMatrix ) const;
33+
static int cubicInterpolation( double p1, double p2, double p3, double p4, double p1x, double p2x, double p3x, double p4x,
34+
double p1y, double p2y, double p3y, double p4y, double p1xy, double p2xy, double p3xy, double p4xy );
35+
};
36+
37+
template <class T> void QgsCubicRasterResampler::yDerivativeMatrix( int nCols, int nRows, double* dstMatrix, const T* srcMatrix ) const
38+
{
39+
double val;
40+
int index = 0;
41+
42+
for( int i = 0; i < nRows; ++i )
43+
{
44+
for( int j = 0; j < nCols; ++j )
45+
{
46+
if( i == 0 )
47+
{
48+
val = srcMatrix[ index + nRows ] - srcMatrix[ index ];
49+
}
50+
else if( i == nRows - 1 )
51+
{
52+
val = srcMatrix[ index ] - srcMatrix[ index - nRows ];
53+
}
54+
else
55+
{
56+
val = ( srcMatrix[ index + nRows ] - srcMatrix[ index - nRows ] ) / 2.0;
57+
}
58+
dstMatrix[index] = val;
59+
++index;
60+
}
61+
}
62+
}
63+
64+
#endif // QGSCUBICRASTERRESAMPLER_H

src/core/raster/qgsrasterlayer.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ email : tim at linfiniti.com
3939
//renderers
4040
#include "qgspalettedrasterrenderer.h"
4141
#include "qgsbilinearrasterresampler.h"
42+
#include "qgscubicrasterresampler.h"
4243
#include "qgsmultibandcolorrenderer.h"
4344

4445
#include <cstdio>
@@ -848,7 +849,8 @@ void QgsRasterLayer::draw( QPainter * theQPainter,
848849
colorArray[( int )colorIt->value] = colorIt->color;
849850
}
850851

851-
QgsBilinearRasterResampler resampler;
852+
//QgsBilinearRasterResampler resampler;
853+
QgsCubicRasterResampler resampler;
852854
QgsPalettedRasterRenderer renderer( mDataProvider, bNumber, colorArray, itemList.size(), &resampler );
853855
renderer.draw( theQPainter, theRasterViewPort, theQgsMapToPixel );
854856
#if 0

0 commit comments

Comments
 (0)