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 #include "imagefilter_p.h"
00036
00037 #include <QPainter>
00038 #include <QImage>
00039 #include <QColor>
00040 #include <QDebug>
00041
00042 #include <cmath>
00043 #include <string.h>
00044
00045 using namespace KIO;
00046
00047 static const quint32 stack_blur8_mul[255] =
00048 {
00049 512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,
00050 454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,
00051 482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,
00052 437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,
00053 497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,
00054 320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,
00055 446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,
00056 329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,
00057 505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,
00058 399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,
00059 324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,
00060 268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,
00061 451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,
00062 385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,
00063 332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,
00064 289,287,285,282,280,278,275,273,271,269,267,265,263,261,259
00065 };
00066
00067 static const quint32 stack_blur8_shr[255] =
00068 {
00069 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
00070 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
00071 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
00072 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
00073 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
00074 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
00075 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
00076 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
00077 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
00078 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
00079 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
00080 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
00081 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
00082 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
00083 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
00084 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
00085 };
00086
00087 inline static void blurHorizontal(QImage &image, unsigned int *stack, int div, int radius)
00088 {
00089 int stackindex;
00090 int stackstart;
00091
00092 quint32 * const pixels = reinterpret_cast<quint32 *>(image.bits());
00093 quint32 pixel;
00094
00095 int w = image.width();
00096 int h = image.height();
00097 int wm = w - 1;
00098
00099 unsigned int mul_sum = stack_blur8_mul[radius];
00100 unsigned int shr_sum = stack_blur8_shr[radius];
00101
00102 unsigned int sum, sum_in, sum_out;
00103
00104 for (int y = 0; y < h; y++)
00105 {
00106 sum = 0;
00107 sum_in = 0;
00108 sum_out = 0;
00109
00110 const int yw = y * w;
00111 pixel = pixels[yw];
00112 for (int i = 0; i <= radius; i++)
00113 {
00114 stack[i] = qAlpha(pixel);
00115
00116 sum += stack[i] * (i + 1);
00117 sum_out += stack[i];
00118 }
00119
00120 for (int i = 1; i <= radius; i++)
00121 {
00122 pixel = pixels[yw + qMin(i, wm)];
00123
00124 unsigned int *stackpix = &stack[i + radius];
00125 *stackpix = qAlpha(pixel);
00126
00127 sum += *stackpix * (radius + 1 - i);
00128 sum_in += *stackpix;
00129 }
00130
00131 stackindex = radius;
00132 for (int x = 0, i = yw; x < w; x++)
00133 {
00134 pixels[i++] = (((sum * mul_sum) >> shr_sum) << 24) & 0xff000000;
00135
00136 sum -= sum_out;
00137
00138 stackstart = stackindex + div - radius;
00139 if (stackstart >= div)
00140 stackstart -= div;
00141
00142 unsigned int *stackpix = &stack[stackstart];
00143
00144 sum_out -= *stackpix;
00145
00146 pixel = pixels[yw + qMin(x + radius + 1, wm)];
00147
00148 *stackpix = qAlpha(pixel);
00149
00150 sum_in += *stackpix;
00151 sum += sum_in;
00152
00153 if (++stackindex >= div)
00154 stackindex = 0;
00155
00156 stackpix = &stack[stackindex];
00157
00158 sum_out += *stackpix;
00159 sum_in -= *stackpix;
00160 }
00161 }
00162 }
00163
00164 inline static void blurVertical(QImage &image, unsigned int *stack, int div, int radius)
00165 {
00166 int stackindex;
00167 int stackstart;
00168
00169 quint32 * const pixels = reinterpret_cast<quint32 *>(image.bits());
00170 quint32 pixel;
00171
00172 int w = image.width();
00173 int h = image.height();
00174 int hm = h - 1;
00175
00176 int mul_sum = stack_blur8_mul[radius];
00177 int shr_sum = stack_blur8_shr[radius];
00178
00179 unsigned int sum, sum_in, sum_out;
00180
00181 for (int x = 0; x < w; x++)
00182 {
00183 sum = 0;
00184 sum_in = 0;
00185 sum_out = 0;
00186
00187 pixel = pixels[x];
00188 for (int i = 0; i <= radius; i++)
00189 {
00190 stack[i] = qAlpha(pixel);
00191
00192 sum += stack[i] * (i + 1);
00193 sum_out += stack[i];
00194 }
00195
00196 for (int i = 1; i <= radius; i++)
00197 {
00198 pixel = pixels[qMin(i, hm) * w + x];
00199
00200 unsigned int *stackpix = &stack[i + radius];
00201 *stackpix = qAlpha(pixel);
00202
00203 sum += *stackpix * (radius + 1 - i);
00204 sum_in += *stackpix;
00205 }
00206
00207 stackindex = radius;
00208 for (int y = 0, i = x; y < h; y++, i += w)
00209 {
00210 pixels[i] = (((sum * mul_sum) >> shr_sum) << 24) & 0xff000000;
00211
00212 sum -= sum_out;
00213
00214 stackstart = stackindex + div - radius;
00215 if (stackstart >= div)
00216 stackstart -= div;
00217
00218 unsigned int *stackpix = &stack[stackstart];
00219
00220 sum_out -= *stackpix;
00221
00222 pixel = pixels[qMin(y + radius + 1, hm) * w + x];
00223
00224 *stackpix = qAlpha(pixel);
00225
00226 sum_in += *stackpix;
00227 sum += sum_in;
00228
00229 if (++stackindex >= div)
00230 stackindex = 0;
00231
00232 stackpix = &stack[stackindex];
00233
00234 sum_out += *stackpix;
00235 sum_in -= *stackpix;
00236 }
00237 }
00238 }
00239
00240 static void stackBlur(QImage &image, float radius)
00241 {
00242 radius = qRound(radius);
00243
00244 int div = int(radius * 2) + 1;
00245 unsigned int *stack = new unsigned int[div];
00246
00247 blurHorizontal(image, stack, div, radius);
00248 blurVertical(image, stack, div, radius);
00249
00250 delete [] stack;
00251 }
00252
00253 void ImageFilter::shadowBlur(QImage &image, float radius, const QColor &color)
00254 {
00255 if (radius < 0)
00256 return;
00257
00258 if (radius > 0)
00259 stackBlur(image, radius);
00260
00261
00262 QPainter p(&image);
00263 p.setCompositionMode(QPainter::CompositionMode_SourceIn);
00264 p.fillRect(image.rect(), color);
00265 }
00266
00267