00001 #ifndef BLUR_CPP
00002 #define BLUR_CPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <cmath>
00023
00024
00025
00026 template<int aprec, int zprec>
00027 static inline void blurinner(unsigned char *bptr, int &zR, int &zG, int &zB, int &zA, int alpha);
00028
00029 template<int aprec,int zprec>
00030 static inline void blurrow(QImage &im, int line, int alpha);
00031
00032 template<int aprec, int zprec>
00033 static inline void blurcol(QImage &im, int col, int alpha);
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 template<int aprec,int zprec>
00051 void expblur(QImage &img, int radius)
00052 {
00053 if (radius < 1) {
00054 return;
00055 }
00056
00057 img = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
00058
00059
00060
00061
00062
00063 int alpha = (int)((1 << aprec) * (1.0f - std::exp(-2.3f / (radius + 1.f))));
00064
00065 int height = img.height();
00066 int width = img.width();
00067 for (int row=0; row<height; row++) {
00068 blurrow<aprec,zprec>(img, row, alpha);
00069 }
00070
00071 for (int col=0; col<width; col++) {
00072 blurcol<aprec,zprec>(img, col, alpha);
00073 }
00074 return;
00075 }
00076
00077 template<int aprec, int zprec>
00078 static inline void blurinner(unsigned char *bptr, int &zR, int &zG, int &zB, int &zA, int alpha)
00079 {
00080 int R, G, B, A;
00081 R = *bptr;
00082 G = *(bptr + 1);
00083 B = *(bptr + 2);
00084 A = *(bptr + 3);
00085
00086 zR += (alpha * ((R << zprec) - zR)) >> aprec;
00087 zG += (alpha * ((G << zprec) - zG)) >> aprec;
00088 zB += (alpha * ((B << zprec) - zB)) >> aprec;
00089 zA += (alpha * ((A << zprec) - zA)) >> aprec;
00090
00091 *bptr = zR >> zprec;
00092 *(bptr+1) = zG >> zprec;
00093 *(bptr+2) = zB >> zprec;
00094 *(bptr+3) = zA >> zprec;
00095 }
00096
00097 template<int aprec,int zprec>
00098 static inline void blurrow(QImage &im, int line, int alpha)
00099 {
00100 int zR, zG, zB, zA;
00101
00102 QRgb *ptr = (QRgb *)im.scanLine(line);
00103 int width = im.width();
00104
00105 zR = *((unsigned char *)ptr ) << zprec;
00106 zG = *((unsigned char *)ptr + 1) << zprec;
00107 zB = *((unsigned char *)ptr + 2) << zprec;
00108 zA = *((unsigned char *)ptr + 3) << zprec;
00109
00110 for (int index=1; index<width; index++) {
00111 blurinner<aprec,zprec>((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha);
00112 }
00113 for (int index=width-2; index>=0; index--) {
00114 blurinner<aprec,zprec>((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha);
00115 }
00116 }
00117
00118 template<int aprec, int zprec>
00119 static inline void blurcol(QImage &im, int col, int alpha)
00120 {
00121 int zR, zG, zB, zA;
00122
00123 QRgb *ptr = (QRgb *)im.bits();
00124 ptr += col;
00125 int height = im.height();
00126 int width = im.width();
00127
00128 zR = *((unsigned char *)ptr ) << zprec;
00129 zG = *((unsigned char *)ptr + 1) << zprec;
00130 zB = *((unsigned char *)ptr + 2) << zprec;
00131 zA = *((unsigned char *)ptr + 3) << zprec;
00132
00133 for (int index=width; index<(height-1)*width; index+=width) {
00134 blurinner<aprec,zprec>((unsigned char *)&ptr[index], zR, zG, zB, zA, alpha);
00135 }
00136
00137 for (int index=(height-2)*width; index>=0; index-=width) {
00138 blurinner<aprec,zprec>((unsigned char *)&ptr[index], zR, zG, zB, zA, alpha);
00139 }
00140 }
00141
00142 template<class T>
00143 inline const T &qClamp(const T &x, const T &low, const T &high)
00144 {
00145 if (x < low) {
00146 return low;
00147 } else if (x > high) {
00148 return high;
00149 } else {
00150 return x;
00151 }
00152 }
00153
00154 #endif