btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / libs / agg / agg_blur.h
blob0860f52e19576b984d1ddebfb5606f6fbfe82999
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
16 // The Stack Blur Algorithm was invented by Mario Klingemann,
17 // mario@quasimondo.com and described here:
18 // http://incubator.quasimondo.com/processing/fast_blur_deluxe.php
19 // (search phrase "Stackblur: Fast But Goodlooking").
20 // The major improvement is that there's no more division table
21 // that was very expensive to create for large blur radii. Insted,
22 // for 8-bit per channel and radius not exceeding 254 the division is
23 // replaced by multiplication and shift.
25 //----------------------------------------------------------------------------
27 #ifndef AGG_BLUR_INCLUDED
28 #define AGG_BLUR_INCLUDED
30 #include "agg_array.h"
31 #include "agg_pixfmt_transposer.h"
33 namespace agg
36 template<class T> struct stack_blur_tables
38 static int16u const g_stack_blur8_mul[255];
39 static int8u const g_stack_blur8_shr[255];
42 //------------------------------------------------------------------------
43 template<class T>
44 int16u const stack_blur_tables<T>::g_stack_blur8_mul[255] =
46 512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,
47 454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,
48 482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,
49 437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,
50 497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,
51 320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,
52 446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,
53 329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,
54 505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,
55 399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,
56 324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,
57 268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,
58 451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,
59 385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,
60 332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,
61 289,287,285,282,280,278,275,273,271,269,267,265,263,261,259
64 //------------------------------------------------------------------------
65 template<class T>
66 int8u const stack_blur_tables<T>::g_stack_blur8_shr[255] =
68 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
69 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
70 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
71 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
72 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
73 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
74 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
75 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
76 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
77 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
78 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
79 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
80 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
81 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
82 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
83 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
88 //==============================================================stack_blur
89 template<class ColorT, class CalculatorT> class stack_blur
91 public:
92 typedef ColorT color_type;
93 typedef CalculatorT calculator_type;
95 //--------------------------------------------------------------------
96 template<class Img> void blur_x(Img& img, unsigned radius)
98 if(radius < 1) return;
100 unsigned x, y, xp, i;
101 unsigned stack_ptr;
102 unsigned stack_start;
104 color_type pix;
105 color_type* stack_pix;
106 calculator_type sum;
107 calculator_type sum_in;
108 calculator_type sum_out;
110 unsigned w = img.width();
111 unsigned h = img.height();
112 unsigned wm = w - 1;
113 unsigned div = radius * 2 + 1;
115 unsigned div_sum = (radius + 1) * (radius + 1);
116 unsigned mul_sum = 0;
117 unsigned shr_sum = 0;
118 unsigned max_val = color_type::base_mask;
120 if(max_val <= 255 && radius < 255)
122 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[radius];
123 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[radius];
126 m_buf.allocate(w, 128);
127 m_stack.allocate(div, 32);
129 for(y = 0; y < h; y++)
131 sum.clear();
132 sum_in.clear();
133 sum_out.clear();
135 pix = img.pixel(0, y);
136 for(i = 0; i <= radius; i++)
138 m_stack[i] = pix;
139 sum.add(pix, i + 1);
140 sum_out.add(pix);
142 for(i = 1; i <= radius; i++)
144 pix = img.pixel((i > wm) ? wm : i, y);
145 m_stack[i + radius] = pix;
146 sum.add(pix, radius + 1 - i);
147 sum_in.add(pix);
150 stack_ptr = radius;
151 for(x = 0; x < w; x++)
153 if(mul_sum) sum.calc_pix(m_buf[x], mul_sum, shr_sum);
154 else sum.calc_pix(m_buf[x], div_sum);
156 sum.sub(sum_out);
158 stack_start = stack_ptr + div - radius;
159 if(stack_start >= div) stack_start -= div;
160 stack_pix = &m_stack[stack_start];
162 sum_out.sub(*stack_pix);
164 xp = x + radius + 1;
165 if(xp > wm) xp = wm;
166 pix = img.pixel(xp, y);
168 *stack_pix = pix;
170 sum_in.add(pix);
171 sum.add(sum_in);
173 ++stack_ptr;
174 if(stack_ptr >= div) stack_ptr = 0;
175 stack_pix = &m_stack[stack_ptr];
177 sum_out.add(*stack_pix);
178 sum_in.sub(*stack_pix);
180 img.copy_color_hspan(0, y, w, &m_buf[0]);
184 //--------------------------------------------------------------------
185 template<class Img> void blur_y(Img& img, unsigned radius)
187 pixfmt_transposer<Img> img2(img);
188 blur_x(img2, radius);
191 //--------------------------------------------------------------------
192 template<class Img> void blur(Img& img, unsigned radius)
194 blur_x(img, radius);
195 pixfmt_transposer<Img> img2(img);
196 blur_x(img2, radius);
199 private:
200 pod_vector<color_type> m_buf;
201 pod_vector<color_type> m_stack;
204 //====================================================stack_blur_calc_rgba
205 template<class T=unsigned> struct stack_blur_calc_rgba
207 typedef T value_type;
208 value_type r,g,b,a;
210 AGG_INLINE void clear()
212 r = g = b = a = 0;
215 template<class ArgT> AGG_INLINE void add(const ArgT& v)
217 r += v.r;
218 g += v.g;
219 b += v.b;
220 a += v.a;
223 template<class ArgT> AGG_INLINE void add(const ArgT& v, unsigned k)
225 r += v.r * k;
226 g += v.g * k;
227 b += v.b * k;
228 a += v.a * k;
231 template<class ArgT> AGG_INLINE void sub(const ArgT& v)
233 r -= v.r;
234 g -= v.g;
235 b -= v.b;
236 a -= v.a;
239 template<class ArgT> AGG_INLINE void calc_pix(ArgT& v, unsigned div)
241 typedef typename ArgT::value_type value_type;
242 v.r = value_type(r / div);
243 v.g = value_type(g / div);
244 v.b = value_type(b / div);
245 v.a = value_type(a / div);
248 template<class ArgT>
249 AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr)
251 typedef typename ArgT::value_type value_type;
252 v.r = value_type((r * mul) >> shr);
253 v.g = value_type((g * mul) >> shr);
254 v.b = value_type((b * mul) >> shr);
255 v.a = value_type((a * mul) >> shr);
260 //=====================================================stack_blur_calc_rgb
261 template<class T=unsigned> struct stack_blur_calc_rgb
263 typedef T value_type;
264 value_type r,g,b;
266 AGG_INLINE void clear()
268 r = g = b = 0;
271 template<class ArgT> AGG_INLINE void add(const ArgT& v)
273 r += v.r;
274 g += v.g;
275 b += v.b;
278 template<class ArgT> AGG_INLINE void add(const ArgT& v, unsigned k)
280 r += v.r * k;
281 g += v.g * k;
282 b += v.b * k;
285 template<class ArgT> AGG_INLINE void sub(const ArgT& v)
287 r -= v.r;
288 g -= v.g;
289 b -= v.b;
292 template<class ArgT> AGG_INLINE void calc_pix(ArgT& v, unsigned div)
294 typedef typename ArgT::value_type value_type;
295 v.r = value_type(r / div);
296 v.g = value_type(g / div);
297 v.b = value_type(b / div);
300 template<class ArgT>
301 AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr)
303 typedef typename ArgT::value_type value_type;
304 v.r = value_type((r * mul) >> shr);
305 v.g = value_type((g * mul) >> shr);
306 v.b = value_type((b * mul) >> shr);
311 //====================================================stack_blur_calc_gray
312 template<class T=unsigned> struct stack_blur_calc_gray
314 typedef T value_type;
315 value_type v;
317 AGG_INLINE void clear()
319 v = 0;
322 template<class ArgT> AGG_INLINE void add(const ArgT& a)
324 v += a.v;
327 template<class ArgT> AGG_INLINE void add(const ArgT& a, unsigned k)
329 v += a.v * k;
332 template<class ArgT> AGG_INLINE void sub(const ArgT& a)
334 v -= a.v;
337 template<class ArgT> AGG_INLINE void calc_pix(ArgT& a, unsigned div)
339 typedef typename ArgT::value_type value_type;
340 a.v = value_type(v / div);
343 template<class ArgT>
344 AGG_INLINE void calc_pix(ArgT& a, unsigned mul, unsigned shr)
346 typedef typename ArgT::value_type value_type;
347 a.v = value_type((v * mul) >> shr);
353 //========================================================stack_blur_gray8
354 template<class Img>
355 void stack_blur_gray8(Img& img, unsigned rx, unsigned ry)
357 unsigned x, y, xp, yp, i;
358 unsigned stack_ptr;
359 unsigned stack_start;
361 const int8u* src_pix_ptr;
362 int8u* dst_pix_ptr;
363 unsigned pix;
364 unsigned stack_pix;
365 unsigned sum;
366 unsigned sum_in;
367 unsigned sum_out;
369 unsigned w = img.width();
370 unsigned h = img.height();
371 unsigned wm = w - 1;
372 unsigned hm = h - 1;
374 unsigned div;
375 unsigned mul_sum;
376 unsigned shr_sum;
378 pod_vector<int8u> stack;
380 if(rx > 0)
382 if(rx > 254) rx = 254;
383 div = rx * 2 + 1;
384 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx];
385 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx];
386 stack.allocate(div);
388 for(y = 0; y < h; y++)
390 sum = sum_in = sum_out = 0;
392 src_pix_ptr = img.pix_ptr(0, y);
393 pix = *src_pix_ptr;
394 for(i = 0; i <= rx; i++)
396 stack[i] = pix;
397 sum += pix * (i + 1);
398 sum_out += pix;
400 for(i = 1; i <= rx; i++)
402 if(i <= wm) src_pix_ptr += Img::pix_step;
403 pix = *src_pix_ptr;
404 stack[i + rx] = pix;
405 sum += pix * (rx + 1 - i);
406 sum_in += pix;
409 stack_ptr = rx;
410 xp = rx;
411 if(xp > wm) xp = wm;
412 src_pix_ptr = img.pix_ptr(xp, y);
413 dst_pix_ptr = img.pix_ptr(0, y);
414 for(x = 0; x < w; x++)
416 *dst_pix_ptr = (sum * mul_sum) >> shr_sum;
417 dst_pix_ptr += Img::pix_step;
419 sum -= sum_out;
421 stack_start = stack_ptr + div - rx;
422 if(stack_start >= div) stack_start -= div;
423 sum_out -= stack[stack_start];
425 if(xp < wm)
427 src_pix_ptr += Img::pix_step;
428 pix = *src_pix_ptr;
429 ++xp;
432 stack[stack_start] = pix;
434 sum_in += pix;
435 sum += sum_in;
437 ++stack_ptr;
438 if(stack_ptr >= div) stack_ptr = 0;
439 stack_pix = stack[stack_ptr];
441 sum_out += stack_pix;
442 sum_in -= stack_pix;
447 if(ry > 0)
449 if(ry > 254) ry = 254;
450 div = ry * 2 + 1;
451 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry];
452 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry];
453 stack.allocate(div);
455 int stride = img.stride();
456 for(x = 0; x < w; x++)
458 sum = sum_in = sum_out = 0;
460 src_pix_ptr = img.pix_ptr(x, 0);
461 pix = *src_pix_ptr;
462 for(i = 0; i <= ry; i++)
464 stack[i] = pix;
465 sum += pix * (i + 1);
466 sum_out += pix;
468 for(i = 1; i <= ry; i++)
470 if(i <= hm) src_pix_ptr += stride;
471 pix = *src_pix_ptr;
472 stack[i + ry] = pix;
473 sum += pix * (ry + 1 - i);
474 sum_in += pix;
477 stack_ptr = ry;
478 yp = ry;
479 if(yp > hm) yp = hm;
480 src_pix_ptr = img.pix_ptr(x, yp);
481 dst_pix_ptr = img.pix_ptr(x, 0);
482 for(y = 0; y < h; y++)
484 *dst_pix_ptr = (sum * mul_sum) >> shr_sum;
485 dst_pix_ptr += stride;
487 sum -= sum_out;
489 stack_start = stack_ptr + div - ry;
490 if(stack_start >= div) stack_start -= div;
491 sum_out -= stack[stack_start];
493 if(yp < hm)
495 src_pix_ptr += stride;
496 pix = *src_pix_ptr;
497 ++yp;
500 stack[stack_start] = pix;
502 sum_in += pix;
503 sum += sum_in;
505 ++stack_ptr;
506 if(stack_ptr >= div) stack_ptr = 0;
507 stack_pix = stack[stack_ptr];
509 sum_out += stack_pix;
510 sum_in -= stack_pix;
518 //========================================================stack_blur_rgb24
519 template<class Img>
520 void stack_blur_rgb24(Img& img, unsigned rx, unsigned ry)
522 typedef typename Img::color_type color_type;
523 typedef typename Img::order_type order_type;
524 enum order_e
526 R = order_type::R,
527 G = order_type::G,
528 B = order_type::B
531 unsigned x, y, xp, yp, i;
532 unsigned stack_ptr;
533 unsigned stack_start;
535 const int8u* src_pix_ptr;
536 int8u* dst_pix_ptr;
537 color_type* stack_pix_ptr;
539 unsigned sum_r;
540 unsigned sum_g;
541 unsigned sum_b;
542 unsigned sum_in_r;
543 unsigned sum_in_g;
544 unsigned sum_in_b;
545 unsigned sum_out_r;
546 unsigned sum_out_g;
547 unsigned sum_out_b;
549 unsigned w = img.width();
550 unsigned h = img.height();
551 unsigned wm = w - 1;
552 unsigned hm = h - 1;
554 unsigned div;
555 unsigned mul_sum;
556 unsigned shr_sum;
558 pod_vector<color_type> stack;
560 if(rx > 0)
562 if(rx > 254) rx = 254;
563 div = rx * 2 + 1;
564 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx];
565 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx];
566 stack.allocate(div);
568 for(y = 0; y < h; y++)
570 sum_r =
571 sum_g =
572 sum_b =
573 sum_in_r =
574 sum_in_g =
575 sum_in_b =
576 sum_out_r =
577 sum_out_g =
578 sum_out_b = 0;
580 src_pix_ptr = img.pix_ptr(0, y);
581 for(i = 0; i <= rx; i++)
583 stack_pix_ptr = &stack[i];
584 stack_pix_ptr->r = src_pix_ptr[R];
585 stack_pix_ptr->g = src_pix_ptr[G];
586 stack_pix_ptr->b = src_pix_ptr[B];
587 sum_r += src_pix_ptr[R] * (i + 1);
588 sum_g += src_pix_ptr[G] * (i + 1);
589 sum_b += src_pix_ptr[B] * (i + 1);
590 sum_out_r += src_pix_ptr[R];
591 sum_out_g += src_pix_ptr[G];
592 sum_out_b += src_pix_ptr[B];
594 for(i = 1; i <= rx; i++)
596 if(i <= wm) src_pix_ptr += Img::pix_width;
597 stack_pix_ptr = &stack[i + rx];
598 stack_pix_ptr->r = src_pix_ptr[R];
599 stack_pix_ptr->g = src_pix_ptr[G];
600 stack_pix_ptr->b = src_pix_ptr[B];
601 sum_r += src_pix_ptr[R] * (rx + 1 - i);
602 sum_g += src_pix_ptr[G] * (rx + 1 - i);
603 sum_b += src_pix_ptr[B] * (rx + 1 - i);
604 sum_in_r += src_pix_ptr[R];
605 sum_in_g += src_pix_ptr[G];
606 sum_in_b += src_pix_ptr[B];
609 stack_ptr = rx;
610 xp = rx;
611 if(xp > wm) xp = wm;
612 src_pix_ptr = img.pix_ptr(xp, y);
613 dst_pix_ptr = img.pix_ptr(0, y);
614 for(x = 0; x < w; x++)
616 dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
617 dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
618 dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
619 dst_pix_ptr += Img::pix_width;
621 sum_r -= sum_out_r;
622 sum_g -= sum_out_g;
623 sum_b -= sum_out_b;
625 stack_start = stack_ptr + div - rx;
626 if(stack_start >= div) stack_start -= div;
627 stack_pix_ptr = &stack[stack_start];
629 sum_out_r -= stack_pix_ptr->r;
630 sum_out_g -= stack_pix_ptr->g;
631 sum_out_b -= stack_pix_ptr->b;
633 if(xp < wm)
635 src_pix_ptr += Img::pix_width;
636 ++xp;
639 stack_pix_ptr->r = src_pix_ptr[R];
640 stack_pix_ptr->g = src_pix_ptr[G];
641 stack_pix_ptr->b = src_pix_ptr[B];
643 sum_in_r += src_pix_ptr[R];
644 sum_in_g += src_pix_ptr[G];
645 sum_in_b += src_pix_ptr[B];
646 sum_r += sum_in_r;
647 sum_g += sum_in_g;
648 sum_b += sum_in_b;
650 ++stack_ptr;
651 if(stack_ptr >= div) stack_ptr = 0;
652 stack_pix_ptr = &stack[stack_ptr];
654 sum_out_r += stack_pix_ptr->r;
655 sum_out_g += stack_pix_ptr->g;
656 sum_out_b += stack_pix_ptr->b;
657 sum_in_r -= stack_pix_ptr->r;
658 sum_in_g -= stack_pix_ptr->g;
659 sum_in_b -= stack_pix_ptr->b;
664 if(ry > 0)
666 if(ry > 254) ry = 254;
667 div = ry * 2 + 1;
668 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry];
669 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry];
670 stack.allocate(div);
672 int stride = img.stride();
673 for(x = 0; x < w; x++)
675 sum_r =
676 sum_g =
677 sum_b =
678 sum_in_r =
679 sum_in_g =
680 sum_in_b =
681 sum_out_r =
682 sum_out_g =
683 sum_out_b = 0;
685 src_pix_ptr = img.pix_ptr(x, 0);
686 for(i = 0; i <= ry; i++)
688 stack_pix_ptr = &stack[i];
689 stack_pix_ptr->r = src_pix_ptr[R];
690 stack_pix_ptr->g = src_pix_ptr[G];
691 stack_pix_ptr->b = src_pix_ptr[B];
692 sum_r += src_pix_ptr[R] * (i + 1);
693 sum_g += src_pix_ptr[G] * (i + 1);
694 sum_b += src_pix_ptr[B] * (i + 1);
695 sum_out_r += src_pix_ptr[R];
696 sum_out_g += src_pix_ptr[G];
697 sum_out_b += src_pix_ptr[B];
699 for(i = 1; i <= ry; i++)
701 if(i <= hm) src_pix_ptr += stride;
702 stack_pix_ptr = &stack[i + ry];
703 stack_pix_ptr->r = src_pix_ptr[R];
704 stack_pix_ptr->g = src_pix_ptr[G];
705 stack_pix_ptr->b = src_pix_ptr[B];
706 sum_r += src_pix_ptr[R] * (ry + 1 - i);
707 sum_g += src_pix_ptr[G] * (ry + 1 - i);
708 sum_b += src_pix_ptr[B] * (ry + 1 - i);
709 sum_in_r += src_pix_ptr[R];
710 sum_in_g += src_pix_ptr[G];
711 sum_in_b += src_pix_ptr[B];
714 stack_ptr = ry;
715 yp = ry;
716 if(yp > hm) yp = hm;
717 src_pix_ptr = img.pix_ptr(x, yp);
718 dst_pix_ptr = img.pix_ptr(x, 0);
719 for(y = 0; y < h; y++)
721 dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
722 dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
723 dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
724 dst_pix_ptr += stride;
726 sum_r -= sum_out_r;
727 sum_g -= sum_out_g;
728 sum_b -= sum_out_b;
730 stack_start = stack_ptr + div - ry;
731 if(stack_start >= div) stack_start -= div;
733 stack_pix_ptr = &stack[stack_start];
734 sum_out_r -= stack_pix_ptr->r;
735 sum_out_g -= stack_pix_ptr->g;
736 sum_out_b -= stack_pix_ptr->b;
738 if(yp < hm)
740 src_pix_ptr += stride;
741 ++yp;
744 stack_pix_ptr->r = src_pix_ptr[R];
745 stack_pix_ptr->g = src_pix_ptr[G];
746 stack_pix_ptr->b = src_pix_ptr[B];
748 sum_in_r += src_pix_ptr[R];
749 sum_in_g += src_pix_ptr[G];
750 sum_in_b += src_pix_ptr[B];
751 sum_r += sum_in_r;
752 sum_g += sum_in_g;
753 sum_b += sum_in_b;
755 ++stack_ptr;
756 if(stack_ptr >= div) stack_ptr = 0;
757 stack_pix_ptr = &stack[stack_ptr];
759 sum_out_r += stack_pix_ptr->r;
760 sum_out_g += stack_pix_ptr->g;
761 sum_out_b += stack_pix_ptr->b;
762 sum_in_r -= stack_pix_ptr->r;
763 sum_in_g -= stack_pix_ptr->g;
764 sum_in_b -= stack_pix_ptr->b;
772 //=======================================================stack_blur_rgba32
773 template<class Img>
774 void stack_blur_rgba32(Img& img, unsigned rx, unsigned ry)
776 typedef typename Img::color_type color_type;
777 typedef typename Img::order_type order_type;
778 enum order_e
780 R = order_type::R,
781 G = order_type::G,
782 B = order_type::B,
783 A = order_type::A
786 unsigned x, y, xp, yp, i;
787 unsigned stack_ptr;
788 unsigned stack_start;
790 const int8u* src_pix_ptr;
791 int8u* dst_pix_ptr;
792 color_type* stack_pix_ptr;
794 unsigned sum_r;
795 unsigned sum_g;
796 unsigned sum_b;
797 unsigned sum_a;
798 unsigned sum_in_r;
799 unsigned sum_in_g;
800 unsigned sum_in_b;
801 unsigned sum_in_a;
802 unsigned sum_out_r;
803 unsigned sum_out_g;
804 unsigned sum_out_b;
805 unsigned sum_out_a;
807 unsigned w = img.width();
808 unsigned h = img.height();
809 unsigned wm = w - 1;
810 unsigned hm = h - 1;
812 unsigned div;
813 unsigned mul_sum;
814 unsigned shr_sum;
816 pod_vector<color_type> stack;
818 if(rx > 0)
820 if(rx > 254) rx = 254;
821 div = rx * 2 + 1;
822 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx];
823 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx];
824 stack.allocate(div);
826 for(y = 0; y < h; y++)
828 sum_r =
829 sum_g =
830 sum_b =
831 sum_a =
832 sum_in_r =
833 sum_in_g =
834 sum_in_b =
835 sum_in_a =
836 sum_out_r =
837 sum_out_g =
838 sum_out_b =
839 sum_out_a = 0;
841 src_pix_ptr = img.pix_ptr(0, y);
842 for(i = 0; i <= rx; i++)
844 stack_pix_ptr = &stack[i];
845 stack_pix_ptr->r = src_pix_ptr[R];
846 stack_pix_ptr->g = src_pix_ptr[G];
847 stack_pix_ptr->b = src_pix_ptr[B];
848 stack_pix_ptr->a = src_pix_ptr[A];
849 sum_r += src_pix_ptr[R] * (i + 1);
850 sum_g += src_pix_ptr[G] * (i + 1);
851 sum_b += src_pix_ptr[B] * (i + 1);
852 sum_a += src_pix_ptr[A] * (i + 1);
853 sum_out_r += src_pix_ptr[R];
854 sum_out_g += src_pix_ptr[G];
855 sum_out_b += src_pix_ptr[B];
856 sum_out_a += src_pix_ptr[A];
858 for(i = 1; i <= rx; i++)
860 if(i <= wm) src_pix_ptr += Img::pix_width;
861 stack_pix_ptr = &stack[i + rx];
862 stack_pix_ptr->r = src_pix_ptr[R];
863 stack_pix_ptr->g = src_pix_ptr[G];
864 stack_pix_ptr->b = src_pix_ptr[B];
865 stack_pix_ptr->a = src_pix_ptr[A];
866 sum_r += src_pix_ptr[R] * (rx + 1 - i);
867 sum_g += src_pix_ptr[G] * (rx + 1 - i);
868 sum_b += src_pix_ptr[B] * (rx + 1 - i);
869 sum_a += src_pix_ptr[A] * (rx + 1 - i);
870 sum_in_r += src_pix_ptr[R];
871 sum_in_g += src_pix_ptr[G];
872 sum_in_b += src_pix_ptr[B];
873 sum_in_a += src_pix_ptr[A];
876 stack_ptr = rx;
877 xp = rx;
878 if(xp > wm) xp = wm;
879 src_pix_ptr = img.pix_ptr(xp, y);
880 dst_pix_ptr = img.pix_ptr(0, y);
881 for(x = 0; x < w; x++)
883 dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
884 dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
885 dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
886 dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum;
887 dst_pix_ptr += Img::pix_width;
889 sum_r -= sum_out_r;
890 sum_g -= sum_out_g;
891 sum_b -= sum_out_b;
892 sum_a -= sum_out_a;
894 stack_start = stack_ptr + div - rx;
895 if(stack_start >= div) stack_start -= div;
896 stack_pix_ptr = &stack[stack_start];
898 sum_out_r -= stack_pix_ptr->r;
899 sum_out_g -= stack_pix_ptr->g;
900 sum_out_b -= stack_pix_ptr->b;
901 sum_out_a -= stack_pix_ptr->a;
903 if(xp < wm)
905 src_pix_ptr += Img::pix_width;
906 ++xp;
909 stack_pix_ptr->r = src_pix_ptr[R];
910 stack_pix_ptr->g = src_pix_ptr[G];
911 stack_pix_ptr->b = src_pix_ptr[B];
912 stack_pix_ptr->a = src_pix_ptr[A];
914 sum_in_r += src_pix_ptr[R];
915 sum_in_g += src_pix_ptr[G];
916 sum_in_b += src_pix_ptr[B];
917 sum_in_a += src_pix_ptr[A];
918 sum_r += sum_in_r;
919 sum_g += sum_in_g;
920 sum_b += sum_in_b;
921 sum_a += sum_in_a;
923 ++stack_ptr;
924 if(stack_ptr >= div) stack_ptr = 0;
925 stack_pix_ptr = &stack[stack_ptr];
927 sum_out_r += stack_pix_ptr->r;
928 sum_out_g += stack_pix_ptr->g;
929 sum_out_b += stack_pix_ptr->b;
930 sum_out_a += stack_pix_ptr->a;
931 sum_in_r -= stack_pix_ptr->r;
932 sum_in_g -= stack_pix_ptr->g;
933 sum_in_b -= stack_pix_ptr->b;
934 sum_in_a -= stack_pix_ptr->a;
939 if(ry > 0)
941 if(ry > 254) ry = 254;
942 div = ry * 2 + 1;
943 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry];
944 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry];
945 stack.allocate(div);
947 int stride = img.stride();
948 for(x = 0; x < w; x++)
950 sum_r =
951 sum_g =
952 sum_b =
953 sum_a =
954 sum_in_r =
955 sum_in_g =
956 sum_in_b =
957 sum_in_a =
958 sum_out_r =
959 sum_out_g =
960 sum_out_b =
961 sum_out_a = 0;
963 src_pix_ptr = img.pix_ptr(x, 0);
964 for(i = 0; i <= ry; i++)
966 stack_pix_ptr = &stack[i];
967 stack_pix_ptr->r = src_pix_ptr[R];
968 stack_pix_ptr->g = src_pix_ptr[G];
969 stack_pix_ptr->b = src_pix_ptr[B];
970 stack_pix_ptr->a = src_pix_ptr[A];
971 sum_r += src_pix_ptr[R] * (i + 1);
972 sum_g += src_pix_ptr[G] * (i + 1);
973 sum_b += src_pix_ptr[B] * (i + 1);
974 sum_a += src_pix_ptr[A] * (i + 1);
975 sum_out_r += src_pix_ptr[R];
976 sum_out_g += src_pix_ptr[G];
977 sum_out_b += src_pix_ptr[B];
978 sum_out_a += src_pix_ptr[A];
980 for(i = 1; i <= ry; i++)
982 if(i <= hm) src_pix_ptr += stride;
983 stack_pix_ptr = &stack[i + ry];
984 stack_pix_ptr->r = src_pix_ptr[R];
985 stack_pix_ptr->g = src_pix_ptr[G];
986 stack_pix_ptr->b = src_pix_ptr[B];
987 stack_pix_ptr->a = src_pix_ptr[A];
988 sum_r += src_pix_ptr[R] * (ry + 1 - i);
989 sum_g += src_pix_ptr[G] * (ry + 1 - i);
990 sum_b += src_pix_ptr[B] * (ry + 1 - i);
991 sum_a += src_pix_ptr[A] * (ry + 1 - i);
992 sum_in_r += src_pix_ptr[R];
993 sum_in_g += src_pix_ptr[G];
994 sum_in_b += src_pix_ptr[B];
995 sum_in_a += src_pix_ptr[A];
998 stack_ptr = ry;
999 yp = ry;
1000 if(yp > hm) yp = hm;
1001 src_pix_ptr = img.pix_ptr(x, yp);
1002 dst_pix_ptr = img.pix_ptr(x, 0);
1003 for(y = 0; y < h; y++)
1005 dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
1006 dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
1007 dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
1008 dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum;
1009 dst_pix_ptr += stride;
1011 sum_r -= sum_out_r;
1012 sum_g -= sum_out_g;
1013 sum_b -= sum_out_b;
1014 sum_a -= sum_out_a;
1016 stack_start = stack_ptr + div - ry;
1017 if(stack_start >= div) stack_start -= div;
1019 stack_pix_ptr = &stack[stack_start];
1020 sum_out_r -= stack_pix_ptr->r;
1021 sum_out_g -= stack_pix_ptr->g;
1022 sum_out_b -= stack_pix_ptr->b;
1023 sum_out_a -= stack_pix_ptr->a;
1025 if(yp < hm)
1027 src_pix_ptr += stride;
1028 ++yp;
1031 stack_pix_ptr->r = src_pix_ptr[R];
1032 stack_pix_ptr->g = src_pix_ptr[G];
1033 stack_pix_ptr->b = src_pix_ptr[B];
1034 stack_pix_ptr->a = src_pix_ptr[A];
1036 sum_in_r += src_pix_ptr[R];
1037 sum_in_g += src_pix_ptr[G];
1038 sum_in_b += src_pix_ptr[B];
1039 sum_in_a += src_pix_ptr[A];
1040 sum_r += sum_in_r;
1041 sum_g += sum_in_g;
1042 sum_b += sum_in_b;
1043 sum_a += sum_in_a;
1045 ++stack_ptr;
1046 if(stack_ptr >= div) stack_ptr = 0;
1047 stack_pix_ptr = &stack[stack_ptr];
1049 sum_out_r += stack_pix_ptr->r;
1050 sum_out_g += stack_pix_ptr->g;
1051 sum_out_b += stack_pix_ptr->b;
1052 sum_out_a += stack_pix_ptr->a;
1053 sum_in_r -= stack_pix_ptr->r;
1054 sum_in_g -= stack_pix_ptr->g;
1055 sum_in_b -= stack_pix_ptr->b;
1056 sum_in_a -= stack_pix_ptr->a;
1064 //===========================================================recursive_blur
1065 template<class ColorT, class CalculatorT> class recursive_blur
1067 public:
1068 typedef ColorT color_type;
1069 typedef CalculatorT calculator_type;
1070 typedef typename color_type::value_type value_type;
1071 typedef typename calculator_type::value_type calc_type;
1073 //--------------------------------------------------------------------
1074 template<class Img> void blur_x(Img& img, double radius)
1076 if(radius < 0.62) return;
1077 if(img.width() < 3) return;
1079 calc_type s = calc_type(radius * 0.5);
1080 calc_type q = calc_type((s < 2.5) ?
1081 3.97156 - 4.14554 * sqrt(1 - 0.26891 * s) :
1082 0.98711 * s - 0.96330);
1084 calc_type q2 = calc_type(q * q);
1085 calc_type q3 = calc_type(q2 * q);
1087 calc_type b0 = calc_type(1.0 / (1.578250 +
1088 2.444130 * q +
1089 1.428100 * q2 +
1090 0.422205 * q3));
1092 calc_type b1 = calc_type( 2.44413 * q +
1093 2.85619 * q2 +
1094 1.26661 * q3);
1096 calc_type b2 = calc_type(-1.42810 * q2 +
1097 -1.26661 * q3);
1099 calc_type b3 = calc_type(0.422205 * q3);
1101 calc_type b = calc_type(1 - (b1 + b2 + b3) * b0);
1103 b1 *= b0;
1104 b2 *= b0;
1105 b3 *= b0;
1107 int w = img.width();
1108 int h = img.height();
1109 int wm = w-1;
1110 int x, y;
1112 m_sum1.allocate(w);
1113 m_sum2.allocate(w);
1114 m_buf.allocate(w);
1116 for(y = 0; y < h; y++)
1118 calculator_type c;
1119 c.from_pix(img.pixel(0, y));
1120 m_sum1[0].calc(b, b1, b2, b3, c, c, c, c);
1121 c.from_pix(img.pixel(1, y));
1122 m_sum1[1].calc(b, b1, b2, b3, c, m_sum1[0], m_sum1[0], m_sum1[0]);
1123 c.from_pix(img.pixel(2, y));
1124 m_sum1[2].calc(b, b1, b2, b3, c, m_sum1[1], m_sum1[0], m_sum1[0]);
1126 for(x = 3; x < w; ++x)
1128 c.from_pix(img.pixel(x, y));
1129 m_sum1[x].calc(b, b1, b2, b3, c, m_sum1[x-1], m_sum1[x-2], m_sum1[x-3]);
1132 m_sum2[wm ].calc(b, b1, b2, b3, m_sum1[wm ], m_sum1[wm ], m_sum1[wm], m_sum1[wm]);
1133 m_sum2[wm-1].calc(b, b1, b2, b3, m_sum1[wm-1], m_sum2[wm ], m_sum2[wm], m_sum2[wm]);
1134 m_sum2[wm-2].calc(b, b1, b2, b3, m_sum1[wm-2], m_sum2[wm-1], m_sum2[wm], m_sum2[wm]);
1135 m_sum2[wm ].to_pix(m_buf[wm ]);
1136 m_sum2[wm-1].to_pix(m_buf[wm-1]);
1137 m_sum2[wm-2].to_pix(m_buf[wm-2]);
1139 for(x = wm-3; x >= 0; --x)
1141 m_sum2[x].calc(b, b1, b2, b3, m_sum1[x], m_sum2[x+1], m_sum2[x+2], m_sum2[x+3]);
1142 m_sum2[x].to_pix(m_buf[x]);
1144 img.copy_color_hspan(0, y, w, &m_buf[0]);
1148 //--------------------------------------------------------------------
1149 template<class Img> void blur_y(Img& img, double radius)
1151 pixfmt_transposer<Img> img2(img);
1152 blur_x(img2, radius);
1155 //--------------------------------------------------------------------
1156 template<class Img> void blur(Img& img, double radius)
1158 blur_x(img, radius);
1159 pixfmt_transposer<Img> img2(img);
1160 blur_x(img2, radius);
1163 private:
1164 agg::pod_vector<calculator_type> m_sum1;
1165 agg::pod_vector<calculator_type> m_sum2;
1166 agg::pod_vector<color_type> m_buf;
1170 //=================================================recursive_blur_calc_rgba
1171 template<class T=double> struct recursive_blur_calc_rgba
1173 typedef T value_type;
1174 typedef recursive_blur_calc_rgba<T> self_type;
1176 value_type r,g,b,a;
1178 template<class ColorT>
1179 AGG_INLINE void from_pix(const ColorT& c)
1181 r = c.r;
1182 g = c.g;
1183 b = c.b;
1184 a = c.a;
1187 AGG_INLINE void calc(value_type b1,
1188 value_type b2,
1189 value_type b3,
1190 value_type b4,
1191 const self_type& c1,
1192 const self_type& c2,
1193 const self_type& c3,
1194 const self_type& c4)
1196 r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r;
1197 g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g;
1198 b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b;
1199 a = b1*c1.a + b2*c2.a + b3*c3.a + b4*c4.a;
1202 template<class ColorT>
1203 AGG_INLINE void to_pix(ColorT& c) const
1205 typedef typename ColorT::value_type cv_type;
1206 c.r = (cv_type)uround(r);
1207 c.g = (cv_type)uround(g);
1208 c.b = (cv_type)uround(b);
1209 c.a = (cv_type)uround(a);
1214 //=================================================recursive_blur_calc_rgb
1215 template<class T=double> struct recursive_blur_calc_rgb
1217 typedef T value_type;
1218 typedef recursive_blur_calc_rgb<T> self_type;
1220 value_type r,g,b;
1222 template<class ColorT>
1223 AGG_INLINE void from_pix(const ColorT& c)
1225 r = c.r;
1226 g = c.g;
1227 b = c.b;
1230 AGG_INLINE void calc(value_type b1,
1231 value_type b2,
1232 value_type b3,
1233 value_type b4,
1234 const self_type& c1,
1235 const self_type& c2,
1236 const self_type& c3,
1237 const self_type& c4)
1239 r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r;
1240 g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g;
1241 b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b;
1244 template<class ColorT>
1245 AGG_INLINE void to_pix(ColorT& c) const
1247 typedef typename ColorT::value_type cv_type;
1248 c.r = (cv_type)uround(r);
1249 c.g = (cv_type)uround(g);
1250 c.b = (cv_type)uround(b);
1255 //================================================recursive_blur_calc_gray
1256 template<class T=double> struct recursive_blur_calc_gray
1258 typedef T value_type;
1259 typedef recursive_blur_calc_gray<T> self_type;
1261 value_type v;
1263 template<class ColorT>
1264 AGG_INLINE void from_pix(const ColorT& c)
1266 v = c.v;
1269 AGG_INLINE void calc(value_type b1,
1270 value_type b2,
1271 value_type b3,
1272 value_type b4,
1273 const self_type& c1,
1274 const self_type& c2,
1275 const self_type& c3,
1276 const self_type& c4)
1278 v = b1*c1.v + b2*c2.v + b3*c3.v + b4*c4.v;
1281 template<class ColorT>
1282 AGG_INLINE void to_pix(ColorT& c) const
1284 typedef typename ColorT::value_type cv_type;
1285 c.v = (cv_type)uround(v);
1294 #endif