KOSMIndoorMap

stackblur.cpp
1/*
2 SPDX-FileCopyrightText: 2006 Zack Rusin <zack@kde.org>
3 SPDX-FileCopyrightText: 2006-2007, 2008 Fredrik Höglund <fredrik@kde.org>
4
5 The stack blur algorithm was invented by Mario Klingemann <mario@quasimondo.com>
6
7 This implementation is based on the version in Anti-Grain Geometry Version 2.4,
8 SPDX-FileCopyrightText: 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
9
10 SPDX-License-Identifier: BSD-2-Clause
11*/
12
13#include "stackblur_p.h"
14
15using namespace KOSMIndoorMap;
16
17#include <QPainter>
18#include <QImage>
19#include <QColor>
20
21#include <cmath>
22#include <string.h>
23
24static const quint32 stack_blur8_mul[255] = {
25 512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512,
26 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512,
27 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456,
28 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512,
29 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328,
30 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456,
31 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335,
32 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512,
33 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405,
34 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328,
35 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271,
36 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456,
37 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388,
38 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335,
39 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292,
40 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259
41};
42
43static const quint32 stack_blur8_shr[255] = {
44 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
45 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
46 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
47 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
48 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
49 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
50 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
51 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
52 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
53 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
54 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
55 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
56 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
57 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
58 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
59 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
60};
61
62inline static void blurHorizontal(QImage &image, unsigned int *stack, int div, int radius)
63{
64 int stackindex;
65 int stackstart;
66
67 quint32 *const pixels = reinterpret_cast<quint32 *>(image.bits());
68 quint32 pixel;
69
70 int w = image.width();
71 int h = image.height();
72 int wm = w - 1;
73
74 unsigned int mul_sum = stack_blur8_mul[radius];
75 unsigned int shr_sum = stack_blur8_shr[radius];
76
77 unsigned int sum, sum_in, sum_out;
78
79 for (int y = 0; y < h; y++) {
80 sum = 0;
81 sum_in = 0;
82 sum_out = 0;
83
84 const int yw = y * w;
85 pixel = pixels[yw];
86 for (int i = 0; i <= radius; i++) {
87 stack[i] = qAlpha(pixel);
88
89 sum += stack[i] * (i + 1);
90 sum_out += stack[i];
91 }
92
93 for (int i = 1; i <= radius; i++) {
94 pixel = pixels[yw + qMin(i, wm)];
95
96 unsigned int *stackpix = &stack[i + radius];
97 *stackpix = qAlpha(pixel);
98
99 sum += *stackpix * (radius + 1 - i);
100 sum_in += *stackpix;
101 }
102
103 stackindex = radius;
104 for (int x = 0, i = yw; x < w; x++) {
105 pixels[i++] = (((sum * mul_sum) >> shr_sum) << 24) & 0xff000000;
106
107 sum -= sum_out;
108
109 stackstart = stackindex + div - radius;
110 if (stackstart >= div) {
111 stackstart -= div;
112 }
113
114 unsigned int *stackpix = &stack[stackstart];
115
116 sum_out -= *stackpix;
117
118 pixel = pixels[yw + qMin(x + radius + 1, wm)];
119
120 *stackpix = qAlpha(pixel);
121
122 sum_in += *stackpix;
123 sum += sum_in;
124
125 if (++stackindex >= div) {
126 stackindex = 0;
127 }
128
129 stackpix = &stack[stackindex];
130
131 sum_out += *stackpix;
132 sum_in -= *stackpix;
133 } // for (x = 0, ...)
134 } // for (y = 0, ...)
135}
136
137inline static void blurVertical(QImage &image, unsigned int *stack, int div, int radius)
138{
139 int stackindex;
140 int stackstart;
141
142 quint32 *const pixels = reinterpret_cast<quint32 *>(image.bits());
143 quint32 pixel;
144
145 int w = image.width();
146 int h = image.height();
147 int hm = h - 1;
148
149 int mul_sum = stack_blur8_mul[radius];
150 int shr_sum = stack_blur8_shr[radius];
151
152 unsigned int sum, sum_in, sum_out;
153
154 for (int x = 0; x < w; x++) {
155 sum = 0;
156 sum_in = 0;
157 sum_out = 0;
158
159 pixel = pixels[x];
160 for (int i = 0; i <= radius; i++) {
161 stack[i] = qAlpha(pixel);
162
163 sum += stack[i] * (i + 1);
164 sum_out += stack[i];
165 }
166
167 for (int i = 1; i <= radius; i++) {
168 pixel = pixels[qMin(i, hm) * w + x];
169
170 unsigned int *stackpix = &stack[i + radius];
171 *stackpix = qAlpha(pixel);
172
173 sum += *stackpix * (radius + 1 - i);
174 sum_in += *stackpix;
175 }
176
177 stackindex = radius;
178 for (int y = 0, i = x; y < h; y++, i += w) {
179 pixels[i] = (((sum * mul_sum) >> shr_sum) << 24) & 0xff000000;
180
181 sum -= sum_out;
182
183 stackstart = stackindex + div - radius;
184 if (stackstart >= div) {
185 stackstart -= div;
186 }
187
188 unsigned int *stackpix = &stack[stackstart];
189
190 sum_out -= *stackpix;
191
192 pixel = pixels[qMin(y + radius + 1, hm) * w + x];
193
194 *stackpix = qAlpha(pixel);
195
196 sum_in += *stackpix;
197 sum += sum_in;
198
199 if (++stackindex >= div) {
200 stackindex = 0;
201 }
202
203 stackpix = &stack[stackindex];
204
205 sum_out += *stackpix;
206 sum_in -= *stackpix;
207 } // for (y = 0, ...)
208 } // for (x = 0, ...)
209}
210
211void StackBlur::blur(QImage &image, float radius)
212{
213 radius = qRound(radius);
214
215 int div = int(radius * 2) + 1;
216 unsigned int *stack = new unsigned int[div];
217
218 blurHorizontal(image, stack, div, radius);
219 blurVertical(image, stack, div, radius);
220
221 delete [] stack;
222}
OSM-based multi-floor indoor maps for buildings.
uchar * bits()
int height() const const
int width() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:20:03 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.