• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE Support
  • Sitemap
  • Contact Us
 

qimageblitz

scalefilter.cpp

Go to the documentation of this file.
00001 /* 
00002  Copyright (C) 2004, 2005, 2007
00003  Daniel M. Duley <daniel.duley@verizon.net>
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions
00007 are met:
00008 
00009 1. Redistributions of source code must retain the above copyright
00010    notice, this list of conditions and the following disclaimer.
00011 2. Redistributions in binary form must reproduce the above copyright
00012    notice, this list of conditions and the following disclaimer in the
00013    documentation and/or other materials provided with the distribution.
00014 
00015 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00016 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00017 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00018 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00019 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00020 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00021 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00022 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00023 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00024 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00025 
00026 */
00027 
00028 /*
00029  Portions of this software are were originally based on ImageMagick's
00030  algorithms. ImageMagick is copyrighted under the following conditions:
00031 
00032 Copyright (C) 2003 ImageMagick Studio, a non-profit organization dedicated to
00033 making software imaging solutions freely available.
00034 
00035 Permission is hereby granted, free of charge, to any person obtaining a copy
00036 of this software and associated documentation files ("ImageMagick"), to deal
00037 in ImageMagick without restriction, including without limitation the rights
00038 to use, copy, modify, merge, publish, distribute, sublicense,  and/or sell
00039 copies of ImageMagick, and to permit persons to whom the ImageMagick is
00040 furnished to do so, subject to the following conditions:
00041 
00042 The above copyright notice and this permission notice shall be included in all
00043 copies or substantial portions of ImageMagick.
00044 
00045 The software is provided "as is", without warranty of any kind, express or
00046 implied, including but not limited to the warranties of merchantability,
00047 fitness for a particular purpose and noninfringement.  In no event shall
00048 ImageMagick Studio be liable for any claim, damages or other liability,
00049 whether in an action of contract, tort or otherwise, arising from, out of or
00050 in connection with ImageMagick or the use or other dealings in ImageMagick.
00051 
00052 Except as contained in this notice, the name of the ImageMagick Studio shall
00053 not be used in advertising or otherwise to promote the sale, use or other
00054 dealings in ImageMagick without prior written authorization from the
00055 ImageMagick Studio.
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     // These arrays were moved from their respective functions because they
00089     // are inline
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         /*Undefined*/ 0.0f,
00152         /*Point*/ 0.0f,
00153         /*Box*/ 0.5f,
00154         /*Triangle*/ 1.0f,
00155         /*Hermite*/ 1.0f,
00156         /*Hanning*/ 1.0f,
00157         /*Hamming*/ 1.0f,
00158         /*Blackman*/ 1.0f,
00159         /*Gaussian*/ 1.25f,
00160         /*Quadratic*/ 1.5f,
00161         /*Cubic*/ 2.0f,
00162         /*Catrom*/ 2.0f,
00163         /*Mitchell*/ 2.0f,
00164         /*Lanczos*/ 3.0f,
00165         /*BlackmanBessel*/ 3.2383f,
00166         /*BlackmanSinc*/ 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 /*support*/){
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 /*support*/){
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 /*support*/){
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 /*support*/){
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 /*support*/){
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 /*support*/){
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 /*support*/){
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 /*support*/){
00281         return(0.5+0.5*std::cos(MagickPI*(double) x));
00282     }
00283 
00284     inline float Hamming(const float x, const float /*support*/){
00285         return(0.54+0.46*std::cos(MagickPI*(double) x));
00286     }
00287 
00288     inline float Hermite(const float x, const float /*support*/){
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 /*support*/){
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 /*support*/){
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 /*support*/){
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 // Horizontal and vertical filters
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             // Normalize
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             // Normalize
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     // Allocate filter contribution info.
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     // Scale
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 

qimageblitz

Skip menu "qimageblitz"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

KDE Support

Skip menu "KDE Support"
  • akonadi
  • Decibel
  • grantlee
  • kdewin
  • phonon
  •     Backend
  • polkit-qt
  • qca
  • qimageblitz
  • soprano
  • strigi
  •     searchclient
  •     streamanalyzer
  •     streams
Generated for KDE Support by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal