00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #include "qimageblitz.h"
00059 #include <cmath>
00060
00070 #define MagickEpsilon 1.0e-6
00071 #define MagickPI 3.14159265358979323846264338327950288419716939937510
00072
00073 namespace BlitzScaleFilter{
00074 typedef struct{
00075 float weight;
00076 unsigned int pixel;
00077 } ContributionInfo;
00078
00079 bool horizontalFilter(QImage *srcImg, QImage *destImg,
00080 float x_factor, float blur,
00081 ContributionInfo *contribution,
00082 Blitz::ScaleFilterType filter);
00083 bool verticalFilter(QImage *srcImg, QImage *destImg,
00084 float y_factor, float blur,
00085 ContributionInfo *contribution,
00086 Blitz::ScaleFilterType filter);
00087
00088
00089
00090 static const float
00091 J1Pone[] = {
00092 0.581199354001606143928050809e+21f,
00093 -0.6672106568924916298020941484e+20f,
00094 0.2316433580634002297931815435e+19f,
00095 -0.3588817569910106050743641413e+17f,
00096 0.2908795263834775409737601689e+15f,
00097 -0.1322983480332126453125473247e+13f,
00098 0.3413234182301700539091292655e+10f,
00099 -0.4695753530642995859767162166e+7f,
00100 0.270112271089232341485679099e+4f
00101 },
00102 J1Qone[] = {
00103 0.11623987080032122878585294e+22f,
00104 0.1185770712190320999837113348e+20f,
00105 0.6092061398917521746105196863e+17f,
00106 0.2081661221307607351240184229e+15f,
00107 0.5243710262167649715406728642e+12f,
00108 0.1013863514358673989967045588e+10f,
00109 0.1501793594998585505921097578e+7f,
00110 0.1606931573481487801970916749e+4f,
00111 0.1e+1
00112 };
00113
00114 static const float
00115 P1Pone[] = {
00116 0.352246649133679798341724373e+5f,
00117 0.62758845247161281269005675e+5f,
00118 0.313539631109159574238669888e+5f,
00119 0.49854832060594338434500455e+4f,
00120 0.2111529182853962382105718e+3f,
00121 0.12571716929145341558495e+1f
00122 },
00123 P1Qone[] = {
00124 0.352246649133679798068390431e+5f,
00125 0.626943469593560511888833731e+5f,
00126 0.312404063819041039923015703e+5f,
00127 0.4930396490181088979386097e+4f,
00128 0.2030775189134759322293574e+3f,
00129 0.1e+1f
00130 };
00131
00132 static const float
00133 Q1Pone[] = {
00134 0.3511751914303552822533318e+3f,
00135 0.7210391804904475039280863e+3f,
00136 0.4259873011654442389886993e+3f,
00137 0.831898957673850827325226e+2f,
00138 0.45681716295512267064405e+1f,
00139 0.3532840052740123642735e-1f
00140 },
00141 Q1Qone[] = {
00142 0.74917374171809127714519505e+4f,
00143 0.154141773392650970499848051e+5f,
00144 0.91522317015169922705904727e+4f,
00145 0.18111867005523513506724158e+4f,
00146 0.1038187585462133728776636e+3f,
00147 0.1e+1
00148 };
00149
00150 static const float filterSupport[Blitz::SincFilter+1] = {
00151 0.0f,
00152 0.0f,
00153 0.5f,
00154 1.0f,
00155 1.0f,
00156 1.0f,
00157 1.0f,
00158 1.0f,
00159 1.25f,
00160 1.5f,
00161 2.0f,
00162 2.0f,
00163 2.0f,
00164 3.0f,
00165 3.2383f,
00166 4.0f
00167 };
00168
00169 inline float J1(float x){
00170 float p, q;
00171 p=J1Pone[8]; q=J1Qone[8];
00172 for(int i=7; i >= 0; i--){
00173 p=p*x*x+J1Pone[i];
00174 q=q*x*x+J1Qone[i];
00175 }
00176 return(p/q);
00177 }
00178
00179 inline float P1(float x){
00180 float p, q;
00181 p=P1Pone[5]; q=P1Qone[5];
00182 for(int i=4; i >= 0; i--){
00183 p=p*(8.0/x)*(8.0/x)+P1Pone[i];
00184 q=q*(8.0/x)*(8.0/x)+P1Qone[i];
00185 }
00186 return(p/q);
00187 }
00188
00189 inline float Q1(float x){
00190 float p, q;
00191 p=Q1Pone[5]; q=Q1Qone[5];
00192 for(int i=4; i >= 0; i--){
00193 p=p*(8.0/x)*(8.0/x)+Q1Pone[i];
00194 q=q*(8.0/x)*(8.0/x)+Q1Qone[i];
00195 }
00196 return(p/q);
00197 }
00198
00199 inline float BesselOrderOne(float x){
00200 float p, q;
00201 if(x == 0.0)
00202 return(0.0);
00203 p = x;
00204 if(x < 0.0)
00205 x = (-x);
00206 if(x < 8.0)
00207 return(p*J1(x));
00208 q = std::sqrt((float) (2.0/(MagickPI*x)))*(P1(x)*(1.0/std::sqrt(2.0)*(std::sin(x)-
00209 std::cos(x)))-8.0/x*Q1(x)*(-1.0/std::sqrt(2.0)*(std::sin(x)+
00210 std::cos(x))));
00211 if (p < 0.0)
00212 q=(-q);
00213 return(q);
00214 }
00215
00216 inline float Bessel(const float x, const float ){
00217 if(x == 0.0)
00218 return((float)(MagickPI/4.0));
00219 return(BesselOrderOne(MagickPI*x)/(2.0*x));
00220 }
00221
00222 inline float Sinc(const float x, const float ){
00223 if(x == 0.0)
00224 return(1.0);
00225 return(std::sin(MagickPI*x)/(MagickPI*x));
00226 }
00227
00228 inline float Blackman(const float x, const float ){
00229 return(0.42+0.5*std::cos(MagickPI*x)+0.08*std::cos(2*MagickPI*x));
00230 }
00231
00232 inline float BlackmanBessel(const float x,const float support){
00233 return(Blackman(x/support,support)*Bessel(x,support));
00234 }
00235
00236 inline float BlackmanSinc(const float x, const float support){
00237 return(Blackman(x/support,support)*Sinc(x,support));
00238 }
00239
00240 inline float Box(const float x, const float ){
00241 if(x < -0.5)
00242 return(0.0);
00243 if(x < 0.5)
00244 return(1.0);
00245 return(0.0);
00246 }
00247
00248 inline float Catrom(const float x, const float ){
00249 if(x < -2.0)
00250 return(0.0);
00251 if(x < -1.0)
00252 return(0.5*(4.0+x*(8.0+x*(5.0+x))));
00253 if(x < 0.0)
00254 return(0.5*(2.0+x*x*(-5.0-3.0*x)));
00255 if(x < 1.0)
00256 return(0.5*(2.0+x*x*(-5.0+3.0*x)));
00257 if(x < 2.0)
00258 return(0.5*(4.0+x*(-8.0+x*(5.0-x))));
00259 return(0.0);
00260 }
00261
00262 inline float Cubic(const float x, const float ){
00263 if(x < -2.0)
00264 return(0.0);
00265 if(x < -1.0)
00266 return((2.0+x)*(2.0+x)*(2.0+x)/6.0);
00267 if(x < 0.0)
00268 return((4.0+x*x*(-6.0-3.0*x))/6.0);
00269 if(x < 1.0)
00270 return((4.0+x*x*(-6.0+3.0*x))/6.0);
00271 if(x < 2.0)
00272 return((2.0-x)*(2.0-x)*(2.0-x)/6.0);
00273 return(0.0);
00274 }
00275
00276 inline float Gaussian(const float x, const float ){
00277 return(std::exp((float)(-2.0*x*x))*std::sqrt(2.0/MagickPI));
00278 }
00279
00280 inline float Hanning(const float x, const float ){
00281 return(0.5+0.5*std::cos(MagickPI*(double) x));
00282 }
00283
00284 inline float Hamming(const float x, const float ){
00285 return(0.54+0.46*std::cos(MagickPI*(double) x));
00286 }
00287
00288 inline float Hermite(const float x, const float ){
00289 if(x < -1.0)
00290 return(0.0);
00291 if(x < 0.0)
00292 return((2.0*(-x)-3.0)*(-x)*(-x)+1.0);
00293 if(x < 1.0)
00294 return((2.0*x-3.0)*x*x+1.0);
00295 return(0.0);
00296 }
00297
00298 inline float Lanczos(const float x, const float support){
00299 if(x < -3.0)
00300 return(0.0);
00301 if(x < 0.0)
00302 return(Sinc(-x,support)*Sinc(-x/3.0,support));
00303 if(x < 3.0)
00304 return(Sinc(x,support)*Sinc(x/3.0,support));
00305 return(0.0);
00306 }
00307
00308 inline float Mitchell(const float x, const float ){
00309 #define B (1.0/3.0)
00310 #define C (1.0/3.0)
00311 #define P0 (( 6.0- 2.0*B )/6.0)
00312 #define P2 ((-18.0+12.0*B+ 6.0*C)/6.0)
00313 #define P3 (( 12.0- 9.0*B- 6.0*C)/6.0)
00314 #define Q0 (( 8.0*B+24.0*C)/6.0)
00315 #define Q1 (( -12.0*B-48.0*C)/6.0)
00316 #define Q2 (( 6.0*B+30.0*C)/6.0)
00317 #define Q3 (( - 1.0*B- 6.0*C)/6.0)
00318 if(x < -2.0)
00319 return(0.0);
00320 if(x < -1.0)
00321 return(Q0-x*(Q1-x*(Q2-x*Q3)));
00322 if(x < 0.0)
00323 return(P0+x*x*(P2-x*P3));
00324 if(x < 1.0)
00325 return(P0+x*x*(P2+x*P3));
00326 if(x < 2.0)
00327 return(Q0+x*(Q1+x*(Q2+x*Q3)));
00328 return(0.0);
00329 }
00330
00331 inline float Quadratic(const float x, const float ){
00332 if(x < -1.5)
00333 return(0.0);
00334 if(x < -0.5)
00335 return(0.5*(x+1.5)*(x+1.5));
00336 if(x < 0.5)
00337 return(0.75-x*x);
00338 if(x < 1.5)
00339 return(0.5*(x-1.5)*(x-1.5));
00340 return(0.0);
00341 }
00342
00343 inline float Triangle(const float x, const float ){
00344 if(x < -1.0)
00345 return(0.0);
00346 if(x < 0.0)
00347 return(1.0+x);
00348 if(x < 1.0)
00349 return(1.0-x);
00350 return(0.0);
00351 }
00352 }
00353
00354 using namespace BlitzScaleFilter;
00355
00356
00357
00358
00359
00360
00361 bool BlitzScaleFilter::horizontalFilter(QImage *srcImg,
00362 QImage *destImg,
00363 float x_factor, float blur,
00364 ContributionInfo *contribution,
00365 Blitz::ScaleFilterType filter)
00366 {
00367 int n, start, stop, i, x, y;
00368 float center, density, scale, support;
00369 float r, g, b, a;
00370 QRgb *srcData = (QRgb *)srcImg->bits();
00371 QRgb *destData = (QRgb *)destImg->bits();
00372 int sw = srcImg->width();
00373 int dw = destImg->width();
00374 QRgb pixel;
00375
00376 scale = blur*qMax(1.0/x_factor, 1.0);
00377 support = scale*filterSupport[filter];
00378 if(support <= 0.5){
00379 support = float(0.5+MagickEpsilon);
00380 scale = 1.0;
00381 }
00382 scale = 1.0/scale;
00383
00384 for(x=0; x < destImg->width(); ++x){
00385 center = (float) (x+0.5)/x_factor;
00386 start = (int)qMax((double)center-support+0.5, (double)0.0);
00387 stop = (int)qMin((double)center+support+0.5, (double)srcImg->width());
00388 density=0.0;
00389
00390 for(n=0; n < (stop-start); ++n){
00391 contribution[n].pixel = start+n;
00392 switch(filter){
00393 case Blitz::UndefinedFilter:
00394 default:
00395 contribution[n].weight =
00396 Box(scale*((float)(start+n)-center+0.5),
00397 filterSupport[filter]);
00398 break;
00399 case Blitz::PointFilter:
00400 contribution[n].weight =
00401 Box(scale*((float)(start+n)-center+0.5),
00402 filterSupport[filter]);
00403 break;
00404 case Blitz::BoxFilter:
00405 contribution[n].weight =
00406 Box(scale*((float)(start+n)-center+0.5),
00407 filterSupport[filter]);
00408 break;
00409 case Blitz::TriangleFilter:
00410 contribution[n].weight =
00411 Triangle(scale*((float)(start+n)-center+0.5),
00412 filterSupport[filter]);
00413 break;
00414 case Blitz::HermiteFilter:
00415 contribution[n].weight =
00416 Hermite(scale*((float)(start+n)-center+0.5),
00417 filterSupport[filter]);
00418 break;
00419 case Blitz::HanningFilter:
00420 contribution[n].weight =
00421 Hanning(scale*((float)(start+n)-center+0.5),
00422 filterSupport[filter]);
00423 break;
00424 case Blitz::HammingFilter:
00425 contribution[n].weight =
00426 Hamming(scale*((float)(start+n)-center+0.5),
00427 filterSupport[filter]);
00428 break;
00429 case Blitz::BlackmanFilter:
00430 contribution[n].weight =
00431 Blackman(scale*((float)(start+n)-center+0.5),
00432 filterSupport[filter]);
00433 break;
00434 case Blitz::GaussianFilter:
00435 contribution[n].weight =
00436 Gaussian(scale*((float)(start+n)-center+0.5),
00437 filterSupport[filter]);
00438 break;
00439 case Blitz::QuadraticFilter:
00440 contribution[n].weight =
00441 Quadratic(scale*((float)(start+n)-center+0.5),
00442 filterSupport[filter]);
00443 break;
00444 case Blitz::CubicFilter:
00445 contribution[n].weight =
00446 Cubic(scale*((float)(start+n)-center+0.5),
00447 filterSupport[filter]);
00448 break;
00449 case Blitz::CatromFilter:
00450 contribution[n].weight =
00451 Catrom(scale*((float)(start+n)-center+0.5),
00452 filterSupport[filter]);
00453 break;
00454 case Blitz::MitchellFilter:
00455 contribution[n].weight =
00456 Mitchell(scale*((float)(start+n)-center+0.5),
00457 filterSupport[filter]);
00458 break;
00459 case Blitz::LanczosFilter:
00460 contribution[n].weight =
00461 Lanczos(scale*((float)(start+n)-center+0.5),
00462 filterSupport[filter]);
00463 break;
00464 case Blitz::BesselFilter:
00465 contribution[n].weight =
00466 BlackmanBessel(scale*((float)(start+n)-center+0.5),
00467 filterSupport[filter]);
00468 break;
00469 case Blitz::SincFilter:
00470 contribution[n].weight =
00471 BlackmanSinc(scale*((float)(start+n)-center+0.5),
00472 filterSupport[filter]);
00473 break;
00474 }
00475 density += contribution[n].weight;
00476 }
00477
00478 if((density != 0.0) && (density != 1.0)){
00479
00480 density = 1.0/density;
00481 for(i=0; i < n; ++i)
00482 contribution[i].weight *= density;
00483 }
00484
00485 for(y=0; y < destImg->height(); ++y){
00486 r = g = b = a = 0;
00487 for(i=0; i < n; ++i){
00488 pixel = *(srcData+(y*sw)+contribution[i].pixel);
00489 r += qRed(pixel)*contribution[i].weight;
00490 g += qGreen(pixel)*contribution[i].weight;
00491 b += qBlue(pixel)*contribution[i].weight;
00492 a += qAlpha(pixel)*contribution[i].weight;
00493 }
00494 r = r < 0 ? 0 : r > 255 ? 255 : r + 0.5;
00495 g = g < 0 ? 0 : g > 255 ? 255 : g + 0.5;
00496 b = b < 0 ? 0 : b > 255 ? 255 : b + 0.5;
00497 a = a < 0 ? 0 : a > 255 ? 255 : a + 0.5;
00498 *(destData+(y*dw)+x) = qRgba((unsigned char)r,
00499 (unsigned char)g,
00500 (unsigned char)b,
00501 (unsigned char)a);
00502 }
00503 }
00504 return(true);
00505 }
00506
00507 bool BlitzScaleFilter::verticalFilter(QImage *srcImg,
00508 QImage *destImg,
00509 float y_factor, float blur,
00510 ContributionInfo *contribution,
00511 Blitz::ScaleFilterType filter)
00512 {
00513 int n, start, stop, i, x, y;
00514 float center, density, scale, support;
00515 float r, g, b, a;
00516 QRgb *srcData = (QRgb *)srcImg->bits();
00517 QRgb *destData = (QRgb *)destImg->bits();
00518 int sw = srcImg->width();
00519 int dw = destImg->width();
00520 QRgb pixel;
00521
00522 scale = blur*qMax(1.0/y_factor, 1.0);
00523 support = scale*filterSupport[filter];
00524 if(support <= 0.5){
00525 support = float(0.5+MagickEpsilon);
00526 scale = 1.0;
00527 }
00528 scale = 1.0/scale;
00529
00530 for(y=0; y < destImg->height(); ++y){
00531 center = (float) (y+0.5)/y_factor;
00532 start = (int)qMax((double)center-support+0.5, (double)0.0);
00533 stop = (int)qMin((double)center+support+0.5, (double)srcImg->height());
00534 density=0.0;
00535
00536 for(n=0; n < (stop-start); ++n){
00537 contribution[n].pixel = start+n;
00538 switch(filter){
00539 case Blitz::UndefinedFilter:
00540 default:
00541 contribution[n].weight =
00542 Box(scale*((float)(start+n)-center+0.5),
00543 filterSupport[filter]);
00544 break;
00545 case Blitz::PointFilter:
00546 contribution[n].weight =
00547 Box(scale*((float)(start+n)-center+0.5),
00548 filterSupport[filter]);
00549 break;
00550 case Blitz::BoxFilter:
00551 contribution[n].weight =
00552 Box(scale*((float)(start+n)-center+0.5),
00553 filterSupport[filter]);
00554 break;
00555
00556 case Blitz::TriangleFilter:
00557 contribution[n].weight =
00558 Triangle(scale*((float)(start+n)-center+0.5),
00559 filterSupport[filter]);
00560 break;
00561 case Blitz::HermiteFilter:
00562 contribution[n].weight =
00563 Hermite(scale*((float)(start+n)-center+0.5),
00564 filterSupport[filter]);
00565 break;
00566 case Blitz::HanningFilter:
00567 contribution[n].weight =
00568 Hanning(scale*((float)(start+n)-center+0.5),
00569 filterSupport[filter]);
00570 break;
00571 case Blitz::HammingFilter:
00572 contribution[n].weight =
00573 Hamming(scale*((float)(start+n)-center+0.5),
00574 filterSupport[filter]);
00575 break;
00576 case Blitz::BlackmanFilter:
00577 contribution[n].weight =
00578 Blackman(scale*((float)(start+n)-center+0.5),
00579 filterSupport[filter]);
00580 break;
00581 case Blitz::GaussianFilter:
00582 contribution[n].weight =
00583 Gaussian(scale*((float)(start+n)-center+0.5),
00584 filterSupport[filter]);
00585 break;
00586 case Blitz::QuadraticFilter:
00587 contribution[n].weight =
00588 Quadratic(scale*((float)(start+n)-center+0.5),
00589 filterSupport[filter]);
00590 break;
00591 case Blitz::CubicFilter:
00592 contribution[n].weight =
00593 Cubic(scale*((float)(start+n)-center+0.5),
00594 filterSupport[filter]);
00595 break;
00596 case Blitz::CatromFilter:
00597 contribution[n].weight =
00598 Catrom(scale*((float)(start+n)-center+0.5),
00599 filterSupport[filter]);
00600 break;
00601 case Blitz::MitchellFilter:
00602 contribution[n].weight =
00603 Mitchell(scale*((float)(start+n)-center+0.5),
00604 filterSupport[filter]);
00605 break;
00606 case Blitz::LanczosFilter:
00607 contribution[n].weight =
00608 Lanczos(scale*((float)(start+n)-center+0.5),
00609 filterSupport[filter]);
00610 break;
00611 case Blitz::BesselFilter:
00612 contribution[n].weight =
00613 BlackmanBessel(scale*((float)(start+n)-center+0.5),
00614 filterSupport[filter]);
00615 break;
00616 case Blitz::SincFilter:
00617 contribution[n].weight =
00618 BlackmanSinc(scale*((float)(start+n)-center+0.5),
00619 filterSupport[filter]);
00620 break;
00621 }
00622 density += contribution[n].weight;
00623 }
00624
00625 if((density != 0.0) && (density != 1.0)){
00626
00627 density = 1.0/density;
00628 for(i=0; i < n; ++i)
00629 contribution[i].weight *= density;
00630 }
00631
00632 for(x=0; x < destImg->width(); ++x){
00633 r = g = b = a = 0;
00634 for(i=0; i < n; ++i){
00635 pixel = *(srcData+(contribution[i].pixel*sw)+x);
00636 r += qRed(pixel)*contribution[i].weight;
00637 g += qGreen(pixel)*contribution[i].weight;
00638 b += qBlue(pixel)*contribution[i].weight;
00639 a += qAlpha(pixel)*contribution[i].weight;
00640 }
00641 r = r < 0 ? 0 : r > 255 ? 255 : r + 0.5;
00642 g = g < 0 ? 0 : g > 255 ? 255 : g + 0.5;
00643 b = b < 0 ? 0 : b > 255 ? 255 : b + 0.5;
00644 a = a < 0 ? 0 : a > 255 ? 255 : a + 0.5;
00645 *(destData+(y*dw)+x) = qRgba((unsigned char)r,
00646 (unsigned char)g,
00647 (unsigned char)b,
00648 (unsigned char)a);
00649 }
00650 }
00651 return(true);
00652 }
00653
00654 QImage Blitz::smoothScaleFilter(QImage &img, int w, int h,
00655 float blur, ScaleFilterType filter,
00656 Qt::AspectRatioMode aspectRatio)
00657 {
00658 return(smoothScaleFilter(img, QSize(w, h), blur, filter, aspectRatio));
00659 }
00660
00661 QImage Blitz::smoothScaleFilter(QImage &img, const QSize &sz,
00662 float blur, ScaleFilterType filter,
00663 Qt::AspectRatioMode aspectRatio)
00664 {
00665 QSize destSize(img.size());
00666 destSize.scale(sz, aspectRatio);
00667 if(img.isNull() || !destSize.isValid())
00668 return(img);
00669 int dw = destSize.width();
00670 int dh = destSize.height();
00671
00672 if(img.depth() != 32){
00673 img = img.convertToFormat(img.hasAlphaChannel() ?
00674 QImage::Format_ARGB32 :
00675 QImage::Format_RGB32);
00676 }
00677 else if(img.format() == QImage::Format_ARGB32_Premultiplied)
00678 img = img.convertToFormat(QImage::Format_ARGB32);
00679
00680 QImage buffer(destSize, img.hasAlphaChannel() ?
00681 QImage::Format_ARGB32 : QImage::Format_RGB32);
00682
00683 ContributionInfo *contribution;
00684 float support, x_factor, x_support, y_factor, y_support;
00685 int i;
00686
00687
00688
00689
00690 x_factor= (float)buffer.width()/img.width();
00691 y_factor= (float)buffer.height()/img.height();
00692 i = (int)LanczosFilter;
00693 if(filter != UndefinedFilter)
00694 i = (int)filter;
00695 else
00696 if((x_factor == 1.0) && (y_factor == 1.0))
00697 i = (int)PointFilter;
00698 else
00699 i = (int)MitchellFilter;
00700 x_support = blur*qMax(1.0/x_factor, 1.0)*filterSupport[i];
00701 y_support = blur*qMax(1.0/y_factor, 1.0)*filterSupport[i];
00702 support = qMax(x_support, y_support);
00703 if(support < filterSupport[i])
00704 support = filterSupport[i];
00705 contribution =
00706 new ContributionInfo[(int)(2.0*qMax((double)support, (double)0.5)+3)];
00707
00708
00709
00710
00711 if((dw*(img.height()+dh)) > (dh*(img.width()+dw))){
00712 QImage tmp(dw, img.height(), buffer.format());
00713 horizontalFilter(&img, &tmp, x_factor, blur, contribution, filter);
00714 verticalFilter(&tmp, &buffer, y_factor, blur, contribution, filter);
00715 }
00716 else{
00717 QImage tmp(img.width(), dh, buffer.format());
00718 verticalFilter(&img, &tmp, y_factor, blur, contribution, filter);
00719 horizontalFilter(&tmp, &buffer, x_factor, blur, contribution, filter);
00720 }
00721
00722 delete[] contribution;
00723 return(buffer);
00724 }
00725
00726