27 #ifndef AGG_BLUR_INCLUDED 28 #define AGG_BLUR_INCLUDED 32 #include "agg_array.h" 33 #include "agg_pixfmt_base.h" 34 #include "agg_pixfmt_transposer.h" 41 static int16u
const g_stack_blur8_mul[255];
42 static int8u
const g_stack_blur8_shr[255];
49 512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,
50 454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,
51 482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,
52 437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,
53 497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,
54 320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,
55 446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,
56 329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,
57 505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,
58 399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,
59 324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,
60 268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,
61 451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,
62 385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,
63 332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,
64 289,287,285,282,280,278,275,273,271,269,267,265,263,261,259
71 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
72 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
73 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
74 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
75 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
76 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
77 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
78 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
79 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
80 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
81 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
82 23, 23, 23, 23, 23, 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, 24,
84 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
85 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
86 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
92 template<
class ColorT,
class CalculatorT>
class stack_blur 95 typedef ColorT color_type;
96 typedef CalculatorT calculator_type;
99 template<
class Img>
void blur_x(Img& img,
unsigned radius)
101 if(radius < 1)
return;
103 unsigned x, y, xp, i;
105 unsigned stack_start;
108 color_type* stack_pix;
110 calculator_type sum_in;
111 calculator_type sum_out;
113 unsigned w = img.width();
114 unsigned h = img.height();
116 unsigned div = radius * 2 + 1;
118 unsigned div_sum = (radius + 1) * (radius + 1);
119 unsigned mul_sum = 0;
120 unsigned shr_sum = 0;
121 unsigned max_val = color_type::base_mask;
123 if(max_val <= 255 && radius < 255)
129 m_buf.allocate(w, 128);
130 m_stack.allocate(div, 32);
132 for(y = 0; y < h; y++)
138 pix = img.pixel(0, y);
139 for(i = 0; i <= radius; i++)
145 for(i = 1; i <= radius; i++)
147 pix = img.pixel((i > wm) ? wm : i, y);
148 m_stack[i + radius] = pix;
149 sum.add(pix, radius + 1 - i);
154 for(x = 0; x < w; x++)
156 if(mul_sum) sum.calc_pix(m_buf[x], mul_sum, shr_sum);
157 else sum.calc_pix(m_buf[x], div_sum);
161 stack_start = stack_ptr + div - radius;
162 if(stack_start >= div) stack_start -= div;
163 stack_pix = &m_stack[stack_start];
165 sum_out.sub(*stack_pix);
169 pix = img.pixel(xp, y);
177 if(stack_ptr >= div) stack_ptr = 0;
178 stack_pix = &m_stack[stack_ptr];
180 sum_out.add(*stack_pix);
181 sum_in.sub(*stack_pix);
183 img.copy_color_hspan(0, y, w, &m_buf[0]);
188 template<
class Img>
void blur_y(Img& img,
unsigned radius)
191 blur_x(img2, radius);
195 template<
class Img>
void blur(Img& img,
unsigned radius)
199 blur_x(img2, radius);
210 typedef T value_type;
213 AGG_INLINE
void clear()
218 template<
class ArgT> AGG_INLINE
void add(
const ArgT& v)
226 template<
class ArgT> AGG_INLINE
void add(
const ArgT& v,
unsigned k)
234 template<
class ArgT> AGG_INLINE
void sub(
const ArgT& v)
242 template<
class ArgT> AGG_INLINE
void calc_pix(ArgT& v,
unsigned div)
244 typedef typename ArgT::value_type value_type;
245 v.r = value_type(r / div);
246 v.g = value_type(g / div);
247 v.b = value_type(b / div);
248 v.a = value_type(a / div);
252 AGG_INLINE
void calc_pix(ArgT& v,
unsigned mul,
unsigned shr)
254 typedef typename ArgT::value_type value_type;
255 v.r = value_type((r * mul) >> shr);
256 v.g = value_type((g * mul) >> shr);
257 v.b = value_type((b * mul) >> shr);
258 v.a = value_type((a * mul) >> shr);
266 typedef T value_type;
269 AGG_INLINE
void clear()
274 template<
class ArgT> AGG_INLINE
void add(
const ArgT& v)
281 template<
class ArgT> AGG_INLINE
void add(
const ArgT& v,
unsigned k)
288 template<
class ArgT> AGG_INLINE
void sub(
const ArgT& v)
295 template<
class ArgT> AGG_INLINE
void calc_pix(ArgT& v,
unsigned div)
297 typedef typename ArgT::value_type value_type;
298 v.r = value_type(r / div);
299 v.g = value_type(g / div);
300 v.b = value_type(b / div);
304 AGG_INLINE
void calc_pix(ArgT& v,
unsigned mul,
unsigned shr)
306 typedef typename ArgT::value_type value_type;
307 v.r = value_type((r * mul) >> shr);
308 v.g = value_type((g * mul) >> shr);
309 v.b = value_type((b * mul) >> shr);
317 typedef T value_type;
320 AGG_INLINE
void clear()
325 template<
class ArgT> AGG_INLINE
void add(
const ArgT& a)
330 template<
class ArgT> AGG_INLINE
void add(
const ArgT& a,
unsigned k)
335 template<
class ArgT> AGG_INLINE
void sub(
const ArgT& a)
340 template<
class ArgT> AGG_INLINE
void calc_pix(ArgT& a,
unsigned div)
342 typedef typename ArgT::value_type value_type;
343 a.v = value_type(v / div);
347 AGG_INLINE
void calc_pix(ArgT& a,
unsigned mul,
unsigned shr)
349 typedef typename ArgT::value_type value_type;
350 a.v = value_type((v * mul) >> shr);
358 void stack_blur_gray8(Img& img,
unsigned rx,
unsigned ry)
360 unsigned x, y, xp, yp, i;
362 unsigned stack_start;
364 const int8u* src_pix_ptr;
372 unsigned w = img.width();
373 unsigned h = img.height();
385 if(rx > 254) rx = 254;
391 for(y = 0; y < h; y++)
393 sum = sum_in = sum_out = 0;
395 src_pix_ptr = img.pix_ptr(0, y);
397 for(i = 0; i <= rx; i++)
400 sum += pix * (i + 1);
403 for(i = 1; i <= rx; i++)
405 if(i <= wm) src_pix_ptr += Img::pix_width;
408 sum += pix * (rx + 1 - i);
415 src_pix_ptr = img.pix_ptr(xp, y);
416 dst_pix_ptr = img.pix_ptr(0, y);
417 for(x = 0; x < w; x++)
419 *dst_pix_ptr = (sum * mul_sum) >> shr_sum;
420 dst_pix_ptr += Img::pix_width;
424 stack_start = stack_ptr + div - rx;
425 if(stack_start >= div) stack_start -= div;
426 sum_out -= stack[stack_start];
430 src_pix_ptr += Img::pix_width;
435 stack[stack_start] = pix;
441 if(stack_ptr >= div) stack_ptr = 0;
442 stack_pix = stack[stack_ptr];
444 sum_out += stack_pix;
452 if(ry > 254) ry = 254;
458 int stride = img.stride();
459 for(x = 0; x < w; x++)
461 sum = sum_in = sum_out = 0;
463 src_pix_ptr = img.pix_ptr(x, 0);
465 for(i = 0; i <= ry; i++)
468 sum += pix * (i + 1);
471 for(i = 1; i <= ry; i++)
473 if(i <= hm) src_pix_ptr += stride;
476 sum += pix * (ry + 1 - i);
483 src_pix_ptr = img.pix_ptr(x, yp);
484 dst_pix_ptr = img.pix_ptr(x, 0);
485 for(y = 0; y < h; y++)
487 *dst_pix_ptr = (sum * mul_sum) >> shr_sum;
488 dst_pix_ptr += stride;
492 stack_start = stack_ptr + div - ry;
493 if(stack_start >= div) stack_start -= div;
494 sum_out -= stack[stack_start];
498 src_pix_ptr += stride;
503 stack[stack_start] = pix;
509 if(stack_ptr >= div) stack_ptr = 0;
510 stack_pix = stack[stack_ptr];
512 sum_out += stack_pix;
523 void stack_blur_rgb24(Img& img,
unsigned rx,
unsigned ry)
525 typedef typename Img::color_type color_type;
526 typedef typename Img::order_type order_type;
534 unsigned x, y, xp, yp, i;
536 unsigned stack_start;
538 const int8u* src_pix_ptr;
540 color_type* stack_pix_ptr;
552 unsigned w = img.width();
553 unsigned h = img.height();
565 if(rx > 254) rx = 254;
571 for(y = 0; y < h; y++)
583 src_pix_ptr = img.pix_ptr(0, y);
584 for(i = 0; i <= rx; i++)
586 stack_pix_ptr = &stack[i];
587 stack_pix_ptr->r = src_pix_ptr[R];
588 stack_pix_ptr->g = src_pix_ptr[G];
589 stack_pix_ptr->b = src_pix_ptr[B];
590 sum_r += src_pix_ptr[R] * (i + 1);
591 sum_g += src_pix_ptr[G] * (i + 1);
592 sum_b += src_pix_ptr[B] * (i + 1);
593 sum_out_r += src_pix_ptr[R];
594 sum_out_g += src_pix_ptr[G];
595 sum_out_b += src_pix_ptr[B];
597 for(i = 1; i <= rx; i++)
599 if(i <= wm) src_pix_ptr += Img::pix_width;
600 stack_pix_ptr = &stack[i + rx];
601 stack_pix_ptr->r = src_pix_ptr[R];
602 stack_pix_ptr->g = src_pix_ptr[G];
603 stack_pix_ptr->b = src_pix_ptr[B];
604 sum_r += src_pix_ptr[R] * (rx + 1 - i);
605 sum_g += src_pix_ptr[G] * (rx + 1 - i);
606 sum_b += src_pix_ptr[B] * (rx + 1 - i);
607 sum_in_r += src_pix_ptr[R];
608 sum_in_g += src_pix_ptr[G];
609 sum_in_b += src_pix_ptr[B];
615 src_pix_ptr = img.pix_ptr(xp, y);
616 dst_pix_ptr = img.pix_ptr(0, y);
617 for(x = 0; x < w; x++)
619 dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
620 dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
621 dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
622 dst_pix_ptr += Img::pix_width;
628 stack_start = stack_ptr + div - rx;
629 if(stack_start >= div) stack_start -= div;
630 stack_pix_ptr = &stack[stack_start];
632 sum_out_r -= stack_pix_ptr->r;
633 sum_out_g -= stack_pix_ptr->g;
634 sum_out_b -= stack_pix_ptr->b;
638 src_pix_ptr += Img::pix_width;
642 stack_pix_ptr->r = src_pix_ptr[R];
643 stack_pix_ptr->g = src_pix_ptr[G];
644 stack_pix_ptr->b = src_pix_ptr[B];
646 sum_in_r += src_pix_ptr[R];
647 sum_in_g += src_pix_ptr[G];
648 sum_in_b += src_pix_ptr[B];
654 if(stack_ptr >= div) stack_ptr = 0;
655 stack_pix_ptr = &stack[stack_ptr];
657 sum_out_r += stack_pix_ptr->r;
658 sum_out_g += stack_pix_ptr->g;
659 sum_out_b += stack_pix_ptr->b;
660 sum_in_r -= stack_pix_ptr->r;
661 sum_in_g -= stack_pix_ptr->g;
662 sum_in_b -= stack_pix_ptr->b;
669 if(ry > 254) ry = 254;
675 int stride = img.stride();
676 for(x = 0; x < w; x++)
688 src_pix_ptr = img.pix_ptr(x, 0);
689 for(i = 0; i <= ry; i++)
691 stack_pix_ptr = &stack[i];
692 stack_pix_ptr->r = src_pix_ptr[R];
693 stack_pix_ptr->g = src_pix_ptr[G];
694 stack_pix_ptr->b = src_pix_ptr[B];
695 sum_r += src_pix_ptr[R] * (i + 1);
696 sum_g += src_pix_ptr[G] * (i + 1);
697 sum_b += src_pix_ptr[B] * (i + 1);
698 sum_out_r += src_pix_ptr[R];
699 sum_out_g += src_pix_ptr[G];
700 sum_out_b += src_pix_ptr[B];
702 for(i = 1; i <= ry; i++)
704 if(i <= hm) src_pix_ptr += stride;
705 stack_pix_ptr = &stack[i + ry];
706 stack_pix_ptr->r = src_pix_ptr[R];
707 stack_pix_ptr->g = src_pix_ptr[G];
708 stack_pix_ptr->b = src_pix_ptr[B];
709 sum_r += src_pix_ptr[R] * (ry + 1 - i);
710 sum_g += src_pix_ptr[G] * (ry + 1 - i);
711 sum_b += src_pix_ptr[B] * (ry + 1 - i);
712 sum_in_r += src_pix_ptr[R];
713 sum_in_g += src_pix_ptr[G];
714 sum_in_b += src_pix_ptr[B];
720 src_pix_ptr = img.pix_ptr(x, yp);
721 dst_pix_ptr = img.pix_ptr(x, 0);
722 for(y = 0; y < h; y++)
724 dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
725 dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
726 dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
727 dst_pix_ptr += stride;
733 stack_start = stack_ptr + div - ry;
734 if(stack_start >= div) stack_start -= div;
736 stack_pix_ptr = &stack[stack_start];
737 sum_out_r -= stack_pix_ptr->r;
738 sum_out_g -= stack_pix_ptr->g;
739 sum_out_b -= stack_pix_ptr->b;
743 src_pix_ptr += stride;
747 stack_pix_ptr->r = src_pix_ptr[R];
748 stack_pix_ptr->g = src_pix_ptr[G];
749 stack_pix_ptr->b = src_pix_ptr[B];
751 sum_in_r += src_pix_ptr[R];
752 sum_in_g += src_pix_ptr[G];
753 sum_in_b += src_pix_ptr[B];
759 if(stack_ptr >= div) stack_ptr = 0;
760 stack_pix_ptr = &stack[stack_ptr];
762 sum_out_r += stack_pix_ptr->r;
763 sum_out_g += stack_pix_ptr->g;
764 sum_out_b += stack_pix_ptr->b;
765 sum_in_r -= stack_pix_ptr->r;
766 sum_in_g -= stack_pix_ptr->g;
767 sum_in_b -= stack_pix_ptr->b;
777 void stack_blur_rgba32(Img& img,
unsigned rx,
unsigned ry)
779 typedef typename Img::color_type color_type;
780 typedef typename Img::order_type order_type;
789 unsigned x, y, xp, yp, i;
791 unsigned stack_start;
793 const int8u* src_pix_ptr;
795 color_type* stack_pix_ptr;
810 unsigned w = img.width();
811 unsigned h = img.height();
823 if(rx > 254) rx = 254;
829 for(y = 0; y < h; y++)
844 src_pix_ptr = img.pix_ptr(0, y);
845 for(i = 0; i <= rx; i++)
847 stack_pix_ptr = &stack[i];
848 stack_pix_ptr->r = src_pix_ptr[R];
849 stack_pix_ptr->g = src_pix_ptr[G];
850 stack_pix_ptr->b = src_pix_ptr[B];
851 stack_pix_ptr->a = src_pix_ptr[A];
852 sum_r += src_pix_ptr[R] * (i + 1);
853 sum_g += src_pix_ptr[G] * (i + 1);
854 sum_b += src_pix_ptr[B] * (i + 1);
855 sum_a += src_pix_ptr[A] * (i + 1);
856 sum_out_r += src_pix_ptr[R];
857 sum_out_g += src_pix_ptr[G];
858 sum_out_b += src_pix_ptr[B];
859 sum_out_a += src_pix_ptr[A];
861 for(i = 1; i <= rx; i++)
863 if(i <= wm) src_pix_ptr += Img::pix_width;
864 stack_pix_ptr = &stack[i + rx];
865 stack_pix_ptr->r = src_pix_ptr[R];
866 stack_pix_ptr->g = src_pix_ptr[G];
867 stack_pix_ptr->b = src_pix_ptr[B];
868 stack_pix_ptr->a = src_pix_ptr[A];
869 sum_r += src_pix_ptr[R] * (rx + 1 - i);
870 sum_g += src_pix_ptr[G] * (rx + 1 - i);
871 sum_b += src_pix_ptr[B] * (rx + 1 - i);
872 sum_a += src_pix_ptr[A] * (rx + 1 - i);
873 sum_in_r += src_pix_ptr[R];
874 sum_in_g += src_pix_ptr[G];
875 sum_in_b += src_pix_ptr[B];
876 sum_in_a += src_pix_ptr[A];
882 src_pix_ptr = img.pix_ptr(xp, y);
883 dst_pix_ptr = img.pix_ptr(0, y);
884 for(x = 0; x < w; x++)
886 dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
887 dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
888 dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
889 dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum;
890 dst_pix_ptr += Img::pix_width;
897 stack_start = stack_ptr + div - rx;
898 if(stack_start >= div) stack_start -= div;
899 stack_pix_ptr = &stack[stack_start];
901 sum_out_r -= stack_pix_ptr->r;
902 sum_out_g -= stack_pix_ptr->g;
903 sum_out_b -= stack_pix_ptr->b;
904 sum_out_a -= stack_pix_ptr->a;
908 src_pix_ptr += Img::pix_width;
912 stack_pix_ptr->r = src_pix_ptr[R];
913 stack_pix_ptr->g = src_pix_ptr[G];
914 stack_pix_ptr->b = src_pix_ptr[B];
915 stack_pix_ptr->a = src_pix_ptr[A];
917 sum_in_r += src_pix_ptr[R];
918 sum_in_g += src_pix_ptr[G];
919 sum_in_b += src_pix_ptr[B];
920 sum_in_a += src_pix_ptr[A];
927 if(stack_ptr >= div) stack_ptr = 0;
928 stack_pix_ptr = &stack[stack_ptr];
930 sum_out_r += stack_pix_ptr->r;
931 sum_out_g += stack_pix_ptr->g;
932 sum_out_b += stack_pix_ptr->b;
933 sum_out_a += stack_pix_ptr->a;
934 sum_in_r -= stack_pix_ptr->r;
935 sum_in_g -= stack_pix_ptr->g;
936 sum_in_b -= stack_pix_ptr->b;
937 sum_in_a -= stack_pix_ptr->a;
944 if(ry > 254) ry = 254;
950 int stride = img.stride();
951 for(x = 0; x < w; x++)
966 src_pix_ptr = img.pix_ptr(x, 0);
967 for(i = 0; i <= ry; i++)
969 stack_pix_ptr = &stack[i];
970 stack_pix_ptr->r = src_pix_ptr[R];
971 stack_pix_ptr->g = src_pix_ptr[G];
972 stack_pix_ptr->b = src_pix_ptr[B];
973 stack_pix_ptr->a = src_pix_ptr[A];
974 sum_r += src_pix_ptr[R] * (i + 1);
975 sum_g += src_pix_ptr[G] * (i + 1);
976 sum_b += src_pix_ptr[B] * (i + 1);
977 sum_a += src_pix_ptr[A] * (i + 1);
978 sum_out_r += src_pix_ptr[R];
979 sum_out_g += src_pix_ptr[G];
980 sum_out_b += src_pix_ptr[B];
981 sum_out_a += src_pix_ptr[A];
983 for(i = 1; i <= ry; i++)
985 if(i <= hm) src_pix_ptr += stride;
986 stack_pix_ptr = &stack[i + ry];
987 stack_pix_ptr->r = src_pix_ptr[R];
988 stack_pix_ptr->g = src_pix_ptr[G];
989 stack_pix_ptr->b = src_pix_ptr[B];
990 stack_pix_ptr->a = src_pix_ptr[A];
991 sum_r += src_pix_ptr[R] * (ry + 1 - i);
992 sum_g += src_pix_ptr[G] * (ry + 1 - i);
993 sum_b += src_pix_ptr[B] * (ry + 1 - i);
994 sum_a += src_pix_ptr[A] * (ry + 1 - i);
995 sum_in_r += src_pix_ptr[R];
996 sum_in_g += src_pix_ptr[G];
997 sum_in_b += src_pix_ptr[B];
998 sum_in_a += src_pix_ptr[A];
1003 if(yp > hm) yp = hm;
1004 src_pix_ptr = img.pix_ptr(x, yp);
1005 dst_pix_ptr = img.pix_ptr(x, 0);
1006 for(y = 0; y < h; y++)
1008 dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
1009 dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
1010 dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
1011 dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum;
1012 dst_pix_ptr += stride;
1019 stack_start = stack_ptr + div - ry;
1020 if(stack_start >= div) stack_start -= div;
1022 stack_pix_ptr = &stack[stack_start];
1023 sum_out_r -= stack_pix_ptr->r;
1024 sum_out_g -= stack_pix_ptr->g;
1025 sum_out_b -= stack_pix_ptr->b;
1026 sum_out_a -= stack_pix_ptr->a;
1030 src_pix_ptr += stride;
1034 stack_pix_ptr->r = src_pix_ptr[R];
1035 stack_pix_ptr->g = src_pix_ptr[G];
1036 stack_pix_ptr->b = src_pix_ptr[B];
1037 stack_pix_ptr->a = src_pix_ptr[A];
1039 sum_in_r += src_pix_ptr[R];
1040 sum_in_g += src_pix_ptr[G];
1041 sum_in_b += src_pix_ptr[B];
1042 sum_in_a += src_pix_ptr[A];
1049 if(stack_ptr >= div) stack_ptr = 0;
1050 stack_pix_ptr = &stack[stack_ptr];
1052 sum_out_r += stack_pix_ptr->r;
1053 sum_out_g += stack_pix_ptr->g;
1054 sum_out_b += stack_pix_ptr->b;
1055 sum_out_a += stack_pix_ptr->a;
1056 sum_in_r -= stack_pix_ptr->r;
1057 sum_in_g -= stack_pix_ptr->g;
1058 sum_in_b -= stack_pix_ptr->b;
1059 sum_in_a -= stack_pix_ptr->a;
1071 typedef ColorT color_type;
1072 typedef CalculatorT calculator_type;
1073 typedef typename color_type::value_type value_type;
1074 typedef typename calculator_type::value_type calc_type;
1077 template<
class Img>
void blur_x(Img& img,
double radius)
1079 if(radius < 0.62)
return;
1080 if(img.width() < 3)
return;
1082 calc_type s = calc_type(radius * 0.5);
1083 calc_type q = calc_type((s < 2.5) ?
1084 3.97156 - 4.14554 * std::sqrt(1 - 0.26891 * s) :
1085 0.98711 * s - 0.96330);
1087 calc_type q2 = calc_type(q * q);
1088 calc_type q3 = calc_type(q2 * q);
1090 calc_type b0 = calc_type(1.0 / (1.578250 +
1095 calc_type b1 = calc_type( 2.44413 * q +
1099 calc_type b2 = calc_type(-1.42810 * q2 +
1102 calc_type b3 = calc_type(0.422205 * q3);
1104 calc_type b = calc_type(1 - (b1 + b2 + b3) * b0);
1110 int w = img.width();
1111 int h = img.height();
1119 for(y = 0; y < h; y++)
1122 c.from_pix(img.pixel(0, y));
1123 m_sum1[0].calc(b, b1, b2, b3, c, c, c, c);
1124 c.from_pix(img.pixel(1, y));
1125 m_sum1[1].calc(b, b1, b2, b3, c, m_sum1[0], m_sum1[0], m_sum1[0]);
1126 c.from_pix(img.pixel(2, y));
1127 m_sum1[2].calc(b, b1, b2, b3, c, m_sum1[1], m_sum1[0], m_sum1[0]);
1129 for(x = 3; x < w; ++x)
1131 c.from_pix(img.pixel(x, y));
1132 m_sum1[x].calc(b, b1, b2, b3, c, m_sum1[x-1], m_sum1[x-2], m_sum1[x-3]);
1135 m_sum2[wm ].calc(b, b1, b2, b3, m_sum1[wm ], m_sum1[wm ], m_sum1[wm], m_sum1[wm]);
1136 m_sum2[wm-1].calc(b, b1, b2, b3, m_sum1[wm-1], m_sum2[wm ], m_sum2[wm], m_sum2[wm]);
1137 m_sum2[wm-2].calc(b, b1, b2, b3, m_sum1[wm-2], m_sum2[wm-1], m_sum2[wm], m_sum2[wm]);
1138 m_sum2[wm ].to_pix(m_buf[wm ]);
1139 m_sum2[wm-1].to_pix(m_buf[wm-1]);
1140 m_sum2[wm-2].to_pix(m_buf[wm-2]);
1142 for(x = wm-3; x >= 0; --x)
1144 m_sum2[x].calc(b, b1, b2, b3, m_sum1[x], m_sum2[x+1], m_sum2[x+2], m_sum2[x+3]);
1145 m_sum2[x].to_pix(m_buf[x]);
1147 img.copy_color_hspan(0, y, w, &m_buf[0]);
1152 template<
class Img>
void blur_y(Img& img,
double radius)
1155 blur_x(img2, radius);
1159 template<
class Img>
void blur(Img& img,
double radius)
1161 blur_x(img, radius);
1163 blur_x(img2, radius);
1176 typedef T value_type;
1181 template<
class ColorT>
1182 AGG_INLINE
void from_pix(
const ColorT& c)
1190 AGG_INLINE
void calc(value_type b1,
1194 const self_type& c1,
1195 const self_type& c2,
1196 const self_type& c3,
1197 const self_type& c4)
1199 r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r;
1200 g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g;
1201 b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b;
1202 a = b1*c1.a + b2*c2.a + b3*c3.a + b4*c4.a;
1205 template<
class ColorT>
1206 AGG_INLINE
void to_pix(ColorT& c)
const 1208 typedef typename ColorT::value_type cv_type;
1220 typedef T value_type;
1225 template<
class ColorT>
1226 AGG_INLINE
void from_pix(
const ColorT& c)
1233 AGG_INLINE
void calc(value_type b1,
1237 const self_type& c1,
1238 const self_type& c2,
1239 const self_type& c3,
1240 const self_type& c4)
1242 r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r;
1243 g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g;
1244 b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b;
1247 template<
class ColorT>
1248 AGG_INLINE
void to_pix(ColorT& c)
const 1250 typedef typename ColorT::value_type cv_type;
1261 typedef T value_type;
1266 template<
class ColorT>
1267 AGG_INLINE
void from_pix(
const ColorT& c)
1272 AGG_INLINE
void calc(value_type b1,
1276 const self_type& c1,
1277 const self_type& c2,
1278 const self_type& c3,
1279 const self_type& c4)
1281 v = b1*c1.v + b2*c2.v + b3*c3.v + b4*c4.v;
1284 template<
class ColorT>
1285 AGG_INLINE
void to_pix(ColorT& c)
const 1287 typedef typename ColorT::value_type cv_type;
1302 template<
class PixFmt>
1306 typedef typename PixFmt::pixel_type pixel_type;
1307 typedef typename PixFmt::value_type value_type;
1308 typedef typename PixFmt::order_type order_type;
1315 void radius(
double r)
1321 double pi = 3.14159;
1323 m_g0 = 1 / std::sqrt(2 * pi);
1324 m_g1 = m_g0 * exp(-n * n);
1327 double sum = m_g0 + 2 * m_g1;
1338 void blur(PixFmt& img,
rect_i bounds)
1341 bounds.clip(
rect_i(0, 0, img.width() - 1, img.height() - 1));
1343 int w = bounds.x2 - bounds.x1 + 1;
1344 int h = bounds.y2 - bounds.y1 + 1;
1346 if (w < 3 || h < 3)
return;
1349 m_buf.allocate(w * 3);
1352 pixel_type * begin = &m_buf[0];
1353 pixel_type * r0 = begin;
1354 pixel_type * r1 = r0 + w;
1355 pixel_type * r2 = r1 + w;
1356 pixel_type * end = r2 + w;
1359 calc_row(img, bounds.x1, bounds.y1, w, r0);
1360 std::memcpy(r1, r0, w *
sizeof(pixel_type));
1365 pixel_type* p = img.pix_value_ptr(bounds.x1, bounds.y1 + y, bounds.x1 + w);
1370 calc_row(img, bounds.x1, bounds.y1 + y + 1, w, r2);
1374 std::memcpy(r2, r1, w *
sizeof(pixel_type));
1378 for (
int x = 0; x < w; ++x)
1380 calc_pixel(*r0++, *r1++, *r2++, *p++);
1383 if (++y >= h)
break;
1386 if (r2 == end) r2 = begin;
1387 else if (r1 == end) r1 = begin;
1388 else if (r0 == end) r0 = begin;
1393 void calc_row(PixFmt& img,
int x,
int y,
int w, pixel_type* row)
1395 const int wm = w - 1;
1397 pixel_type* p = img.pix_value_ptr(x, y, w);
1401 pixel_type* p1 = c + 1;
1402 pixel_type* p2 = c + 2;
1403 pixel_type* end = c + 3;
1406 for (
int x = 0; x < wm; ++x)
1408 *p2 = *(p = p->next());
1410 calc_pixel(*p0++, *p1++, *p2++, *row++);
1412 if (p0 == end) p0 = c;
1413 else if (p1 == end) p1 = c;
1414 else if (p2 == end) p2 = c;
1417 calc_pixel(*p0, *p1, *p1, *row);
1421 pixel_type
const & c1,
1422 pixel_type
const & c2,
1423 pixel_type
const & c3,
1426 calc_pixel(c1, c2, c3, x, PixFmt::pixfmt_category());
1430 pixel_type
const & c1,
1431 pixel_type
const & c2,
1432 pixel_type
const & c3,
1436 x.c[0] = calc_value(c1.c[0], c2.c[0], c3.c[0]);
1440 pixel_type
const & c1,
1441 pixel_type
const & c2,
1442 pixel_type
const & c3,
1446 enum { R = order_type::R, G = order_type::G, B = order_type::B };
1447 x.c[R] = calc_value(c1.c[R], c2.c[R], c3.c[R]);
1448 x.c[G] = calc_value(c1.c[G], c2.c[G], c3.c[G]);
1449 x.c[B] = calc_value(c1.c[B], c2.c[B], c3.c[B]);
1453 pixel_type
const & c1,
1454 pixel_type
const & c2,
1455 pixel_type
const & c3,
1459 enum { R = order_type::R, G = order_type::G, B = order_type::B, A = order_type::A };
1460 x.c[R] = calc_value(c1.c[R], c2.c[R], c3.c[R]);
1461 x.c[G] = calc_value(c1.c[G], c2.c[G], c3.c[G]);
1462 x.c[B] = calc_value(c1.c[B], c2.c[B], c3.c[B]);
1463 x.c[A] = calc_value(c1.c[A], c2.c[A], c3.c[A]);
1466 value_type calc_value(value_type v1, value_type v2, value_type v3)
1468 return value_type(m_g1 * v1 + m_g0 * v2 + m_g1 * v3);
1477 template<
class PixFmt>
1478 void apply_slight_blur(PixFmt& img,
const rect_i& bounds,
double r = 1)
1483 template<
class PixFmt>
1484 void apply_slight_blur(PixFmt& img,
double r = 1)
1489 template<
class PixFmt>
1495 template<
class PixFmt>