File indexing completed on 2024-11-17 04:17:25
0001 /* 0002 SPDX-FileCopyrightText: 2006 Zack Rusin <zack@kde.org> 0003 SPDX-FileCopyrightText: 2006-2007, 2008 Fredrik Höglund <fredrik@kde.org> 0004 0005 The stack blur algorithm was invented by Mario Klingemann <mario@quasimondo.com> 0006 0007 This implementation is based on the version in Anti-Grain Geometry Version 2.4, 0008 SPDX-FileCopyrightText: 2002-2005 Maxim Shemanarev (http://www.antigrain.com) 0009 0010 SPDX-License-Identifier: BSD-2-Clause 0011 */ 0012 0013 #include "stackblur_p.h" 0014 0015 using namespace KOSMIndoorMap; 0016 0017 #include <QPainter> 0018 #include <QImage> 0019 #include <QColor> 0020 0021 #include <cmath> 0022 #include <string.h> 0023 0024 static const quint32 stack_blur8_mul[255] = { 0025 512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, 0026 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, 0027 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, 0028 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, 0029 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, 0030 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, 0031 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, 0032 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, 0033 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, 0034 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, 0035 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, 0036 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, 0037 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, 0038 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, 0039 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, 0040 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259 0041 }; 0042 0043 static const quint32 stack_blur8_shr[255] = { 0044 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 0045 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 0046 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 0047 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 0048 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0049 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 0050 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 0051 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 0052 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 0053 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 0054 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 0055 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0056 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0057 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0058 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0059 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 0060 }; 0061 0062 inline static void blurHorizontal(QImage &image, unsigned int *stack, int div, int radius) 0063 { 0064 int stackindex; 0065 int stackstart; 0066 0067 quint32 *const pixels = reinterpret_cast<quint32 *>(image.bits()); 0068 quint32 pixel; 0069 0070 int w = image.width(); 0071 int h = image.height(); 0072 int wm = w - 1; 0073 0074 unsigned int mul_sum = stack_blur8_mul[radius]; 0075 unsigned int shr_sum = stack_blur8_shr[radius]; 0076 0077 unsigned int sum, sum_in, sum_out; 0078 0079 for (int y = 0; y < h; y++) { 0080 sum = 0; 0081 sum_in = 0; 0082 sum_out = 0; 0083 0084 const int yw = y * w; 0085 pixel = pixels[yw]; 0086 for (int i = 0; i <= radius; i++) { 0087 stack[i] = qAlpha(pixel); 0088 0089 sum += stack[i] * (i + 1); 0090 sum_out += stack[i]; 0091 } 0092 0093 for (int i = 1; i <= radius; i++) { 0094 pixel = pixels[yw + qMin(i, wm)]; 0095 0096 unsigned int *stackpix = &stack[i + radius]; 0097 *stackpix = qAlpha(pixel); 0098 0099 sum += *stackpix * (radius + 1 - i); 0100 sum_in += *stackpix; 0101 } 0102 0103 stackindex = radius; 0104 for (int x = 0, i = yw; x < w; x++) { 0105 pixels[i++] = (((sum * mul_sum) >> shr_sum) << 24) & 0xff000000; 0106 0107 sum -= sum_out; 0108 0109 stackstart = stackindex + div - radius; 0110 if (stackstart >= div) { 0111 stackstart -= div; 0112 } 0113 0114 unsigned int *stackpix = &stack[stackstart]; 0115 0116 sum_out -= *stackpix; 0117 0118 pixel = pixels[yw + qMin(x + radius + 1, wm)]; 0119 0120 *stackpix = qAlpha(pixel); 0121 0122 sum_in += *stackpix; 0123 sum += sum_in; 0124 0125 if (++stackindex >= div) { 0126 stackindex = 0; 0127 } 0128 0129 stackpix = &stack[stackindex]; 0130 0131 sum_out += *stackpix; 0132 sum_in -= *stackpix; 0133 } // for (x = 0, ...) 0134 } // for (y = 0, ...) 0135 } 0136 0137 inline static void blurVertical(QImage &image, unsigned int *stack, int div, int radius) 0138 { 0139 int stackindex; 0140 int stackstart; 0141 0142 quint32 *const pixels = reinterpret_cast<quint32 *>(image.bits()); 0143 quint32 pixel; 0144 0145 int w = image.width(); 0146 int h = image.height(); 0147 int hm = h - 1; 0148 0149 int mul_sum = stack_blur8_mul[radius]; 0150 int shr_sum = stack_blur8_shr[radius]; 0151 0152 unsigned int sum, sum_in, sum_out; 0153 0154 for (int x = 0; x < w; x++) { 0155 sum = 0; 0156 sum_in = 0; 0157 sum_out = 0; 0158 0159 pixel = pixels[x]; 0160 for (int i = 0; i <= radius; i++) { 0161 stack[i] = qAlpha(pixel); 0162 0163 sum += stack[i] * (i + 1); 0164 sum_out += stack[i]; 0165 } 0166 0167 for (int i = 1; i <= radius; i++) { 0168 pixel = pixels[qMin(i, hm) * w + x]; 0169 0170 unsigned int *stackpix = &stack[i + radius]; 0171 *stackpix = qAlpha(pixel); 0172 0173 sum += *stackpix * (radius + 1 - i); 0174 sum_in += *stackpix; 0175 } 0176 0177 stackindex = radius; 0178 for (int y = 0, i = x; y < h; y++, i += w) { 0179 pixels[i] = (((sum * mul_sum) >> shr_sum) << 24) & 0xff000000; 0180 0181 sum -= sum_out; 0182 0183 stackstart = stackindex + div - radius; 0184 if (stackstart >= div) { 0185 stackstart -= div; 0186 } 0187 0188 unsigned int *stackpix = &stack[stackstart]; 0189 0190 sum_out -= *stackpix; 0191 0192 pixel = pixels[qMin(y + radius + 1, hm) * w + x]; 0193 0194 *stackpix = qAlpha(pixel); 0195 0196 sum_in += *stackpix; 0197 sum += sum_in; 0198 0199 if (++stackindex >= div) { 0200 stackindex = 0; 0201 } 0202 0203 stackpix = &stack[stackindex]; 0204 0205 sum_out += *stackpix; 0206 sum_in -= *stackpix; 0207 } // for (y = 0, ...) 0208 } // for (x = 0, ...) 0209 } 0210 0211 void StackBlur::blur(QImage &image, float radius) 0212 { 0213 radius = qRound(radius); 0214 0215 int div = int(radius * 2) + 1; 0216 unsigned int *stack = new unsigned int[div]; 0217 0218 blurHorizontal(image, stack, div, radius); 0219 blurVertical(image, stack, div, radius); 0220 0221 delete [] stack; 0222 }