#ifndef BLUR_CPP #define BLUR_CPP /* * Copyright 2007 Jani Huhtanen <jani.huhtanen@tut.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License version 2 as * published by the Free Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include <cmath> // Exponential blur, Jani Huhtanen, 2006 // template<int aprec, int zprec> static inline void blurinner(unsigned char *bptr, int &zR, int &zG, int &zB, int &zA, int alpha); template<int aprec,int zprec> static inline void blurrow( QImage & im, int line, int alpha); template<int aprec, int zprec> static inline void blurcol( QImage & im, int col, int alpha); /* * expblur(QImage &img, int radius) * * In-place blur of image 'img' with kernel * of approximate radius 'radius'. * * Blurs with two sided exponential impulse * response. * * aprec = precision of alpha parameter * in fixed-point format 0.aprec * * zprec = precision of state parameters * zR,zG,zB and zA in fp format 8.zprec */ template<int aprec,int zprec> void expblur( QImage &img, int radius ) { if(radius<1) return; /* Calculate the alpha such that 90% of the kernel is within the radius. (Kernel extends to infinity) */ int alpha = (int)((1<<aprec)*(1.0f-std::exp(-2.3f/(radius+1.f)))); for(int row=0;row<img.height();row++) { blurrow<aprec,zprec>(img,row,alpha); } for(int col=0;col<img.width();col++) { blurcol<aprec,zprec>(img,col,alpha); } return; } template<int aprec, int zprec> static inline void blurinner(unsigned char *bptr, int &zR, int &zG, int &zB, int &zA, int alpha) { int R,G,B,A; R = *bptr; G = *(bptr+1); B = *(bptr+2); A = *(bptr+3); zR += (alpha * ((R<<zprec)-zR))>>aprec; zG += (alpha * ((G<<zprec)-zG))>>aprec; zB += (alpha * ((B<<zprec)-zB))>>aprec; zA += (alpha * ((A<<zprec)-zA))>>aprec; *bptr = zR>>zprec; *(bptr+1) = zG>>zprec; *(bptr+2) = zB>>zprec; *(bptr+3) = zA>>zprec; } template<int aprec,int zprec> static inline void blurrow( QImage & im, int line, int alpha) { int zR,zG,zB,zA; QRgb *ptr = (QRgb *)im.scanLine(line); zR = *((unsigned char *)ptr )<<zprec; zG = *((unsigned char *)ptr + 1)<<zprec; zB = *((unsigned char *)ptr + 2)<<zprec; zA = *((unsigned char *)ptr + 3)<<zprec; for(int index=1; index<im.width(); index++) { blurinner<aprec,zprec>((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha); } for(int index=im.width()-2; index>=0; index--) { blurinner<aprec,zprec>((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha); } } template<int aprec, int zprec> static inline void blurcol( QImage & im, int col, int alpha) { int zR,zG,zB,zA; QRgb *ptr = (QRgb *)im.bits(); ptr+=col; zR = *((unsigned char *)ptr )<<zprec; zG = *((unsigned char *)ptr + 1)<<zprec; zB = *((unsigned char *)ptr + 2)<<zprec; zA = *((unsigned char *)ptr + 3)<<zprec; for(int index=im.width(); index<(im.height()-1)*im.width(); index+=im.width()) { blurinner<aprec,zprec>((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha); } for(int index=(im.height()-2)*im.width(); index>=0; index-=im.width()) { blurinner<aprec,zprec>((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha); } } template<class T> inline const T& qClamp(const T &x, const T &low, const T &high) { if (x < low) return low; else if (x > high) return high; else return x; } #endif