1
1
/* This file is part of the KDE project
2
2
* Copyright (c) 2009 Jan Hambrecht <jaham@gmx.net>
4
4
* This library is free software; you can redistribute it and/or
5
5
* modify it under the terms of the GNU Lesser General Public
6
6
* License as published by the Free Software Foundation; either
7
7
* version 2 of the License, or (at your option) any later version.
9
9
* This library is distributed in the hope that it will be useful,
10
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
12
* Library General Public License for more details.
14
14
* You should have received a copy of the GNU Lesser General Public License
15
15
* along with this library; see the file COPYING.LIB. If not, write to
16
16
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
37
38
QRgb *pix = (QRgb*)img.bits();
38
39
int w = img.width();
39
40
int h = img.height();
43
int div = radius+radius+1;
44
int div = radius + radius + 1;
45
46
int *r = new int[wh];
46
47
int *g = new int[wh];
47
48
int *b = new int[wh];
48
49
int *a = new int[wh];
49
50
int rsum, gsum, bsum, asum, x, y, i, yp, yi, yw;
51
int *vmin = new int[qMax(w,h)];
53
int divsum = (div+1)>>1;
52
int *vmin = new int[qMax(w, h)];
54
int divsum = (div + 1) >> 1;
55
56
int *dv = new int[256*divsum];
56
for (i=0; i < 256*divsum; ++i) {
57
for (i = 0; i < 256*divsum; ++i) {
62
63
int **stack = new int*[div];
63
for(int i = 0; i < div; ++i) {
64
for (int i = 0; i < div; ++i) {
64
65
stack[i] = new int[4];
73
74
int routsum, goutsum, boutsum, aoutsum;
74
75
int rinsum, ginsum, binsum, ainsum;
76
for (y = 0; y < h; ++y){
77
for (y = 0; y < h; ++y) {
77
78
rinsum = ginsum = binsum = ainsum
78
= routsum = goutsum = boutsum = aoutsum
79
= rsum = gsum = bsum = asum = 0;
80
for(i =- radius; i <= radius; ++i) {
81
p = pix[yi+qMin(wm,qMax(i,0))];
79
= routsum = goutsum = boutsum = aoutsum
80
= rsum = gsum = bsum = asum = 0;
81
for (i = - radius; i <= radius; ++i) {
82
p = pix[yi+qMin(wm, qMax(i, 0))];
82
83
sir = stack[i+radius];
84
85
sir[1] = qGreen(p);
86
87
sir[3] = qAlpha(p);
106
107
stackpointer = radius;
108
for (x=0; x < w; ++x) {
109
for (x = 0; x < w; ++x) {
110
111
r[yi] = dv[rsum];
111
112
g[yi] = dv[gsum];
112
113
b[yi] = dv[bsum];
113
114
a[yi] = dv[asum];
120
stackstart = stackpointer-radius+div;
121
stackstart = stackpointer - radius + div;
121
122
sir = stack[stackstart%div];
123
124
routsum -= sir[0];
124
125
goutsum -= sir[1];
125
126
boutsum -= sir[2];
126
127
aoutsum -= sir[3];
129
vmin[x] = qMin(x+radius+1,wm);
130
vmin[x] = qMin(x + radius + 1, wm);
131
132
p = pix[yw+vmin[x]];
133
134
sir[0] = qRed(p);
134
135
sir[1] = qGreen(p);
135
136
sir[2] = qBlue(p);
136
137
sir[3] = qAlpha(p);
138
139
rinsum += sir[0];
139
140
ginsum += sir[1];
140
141
binsum += sir[2];
141
142
ainsum += sir[3];
148
stackpointer = (stackpointer+1)%div;
149
stackpointer = (stackpointer + 1) % div;
149
150
sir = stack[(stackpointer)%div];
151
152
routsum += sir[0];
152
153
goutsum += sir[1];
153
154
boutsum += sir[2];
154
155
aoutsum += sir[3];
156
157
rinsum -= sir[0];
157
158
ginsum -= sir[1];
158
159
binsum -= sir[2];
159
160
ainsum -= sir[3];
165
for (x=0; x < w; ++x){
166
rinsum = ginsum = binsum = ainsum
167
= routsum = goutsum = boutsum = aoutsum
168
= rsum = gsum = bsum = asum = 0;
172
for(i=-radius; i <= radius; ++i) {
166
for (x = 0; x < w; ++x) {
167
rinsum = ginsum = binsum = ainsum
168
= routsum = goutsum = boutsum = aoutsum
169
= rsum = gsum = bsum = asum = 0;
173
for (i = -radius; i <= radius; ++i) {
174
yi = qMax(0, yp) + x;
175
176
sir = stack[i+radius];
190
191
rinsum += sir[0];
191
192
ginsum += sir[1];
197
198
boutsum += sir[2];
198
199
aoutsum += sir[3];
207
208
stackpointer = radius;
209
for (y=0; y < h; ++y){
210
for (y = 0; y < h; ++y) {
210
211
pix[yi] = qRgba(dv[rsum], dv[gsum], dv[bsum], dv[asum]);
217
stackstart = stackpointer-radius+div;
218
stackstart = stackpointer - radius + div;
218
219
sir = stack[stackstart%div];
220
221
routsum -= sir[0];
221
222
goutsum -= sir[1];
222
223
boutsum -= sir[2];
223
224
aoutsum -= sir[3];
226
vmin[y] = qMin(y+r1,hm)*w;
227
vmin[y] = qMin(y + r1, hm) * w;
235
236
rinsum += sir[0];
236
237
ginsum += sir[1];
237
238
binsum += sir[2];
238
239
ainsum += sir[3];
245
stackpointer = (stackpointer+1)%div;
246
stackpointer = (stackpointer + 1) % div;
246
247
sir = stack[stackpointer];
248
249
routsum += sir[0];
249
250
goutsum += sir[1];
250
251
boutsum += sir[2];
251
252
aoutsum += sir[3];
253
254
rinsum -= sir[0];
254
255
ginsum -= sir[1];
255
256
binsum -= sir[2];
256
257
ainsum -= sir[3];
268
for(int i = 0; i < div; ++i) {
269
for (int i = 0; i < div; ++i) {
269
270
delete [] stack[i];
274
275
BlurEffect::BlurEffect()
275
: KoFilterEffect(BlurEffectId, i18n( "Gaussian blur" ))
276
: KoFilterEffect(BlurEffectId, i18n("Gaussian blur"))
293
294
if (m_deviation.x() == 0.0 || m_deviation.y() == 0.0)
296
297
// TODO: take filter region into account
297
298
// TODO: blur with different kernels in x and y
298
299
// convert from bounding box coordinates
299
QPointF dev = context.coordinateTransformation().map(m_deviation);
300
QPointF dev = context.toUserSpace(m_deviation);
300
301
// transform to view coordinates
301
302
dev = context.viewConverter()->documentToView(dev);
303
304
QImage result = image;
304
305
fastbluralpha(result, dev.x());
309
bool BlurEffect::load(const KoXmlElement &element, const QMatrix &matrix)
310
bool BlurEffect::load(const KoXmlElement &element, const KoFilterEffectLoadingContext &context)
311
312
if (element.tagName() != id())
314
315
QString deviationStr = element.attribute("stdDeviation");
315
QStringList params = deviationStr.trimmed().split( ',' );
317
switch(params.count()) {
316
QStringList params = deviationStr.replace(',', ' ').simplified().split(' ');
318
switch (params.count()) {
319
320
m_deviation.rx() = params[0].toDouble();
320
321
m_deviation.ry() = m_deviation.x();
330
m_deviation = matrix.map(m_deviation);
331
m_deviation = context.convertFilterPrimitiveUnits(m_deviation);
335
336
void BlurEffect::save(KoXmlWriter &writer)
337
338
writer.startElement(BlurEffectId);
339
340
saveCommonAttributes(writer);
341
342
if (m_deviation.x() != m_deviation.y()) {
342
343
writer.addAttribute("stdDeviation", QString("%1, %2").arg(m_deviation.x()).arg(m_deviation.y()));
344
345
writer.addAttribute("stdDeviation", m_deviation.x());
347
348
writer.endElement();