Anti-Grain Geometry - AGG (libagg)
2.5
|
00001 //---------------------------------------------------------------------------- 00002 // Anti-Grain Geometry (AGG) - Version 2.5 00003 // A high quality rendering engine for C++ 00004 // Copyright (C) 2002-2006 Maxim Shemanarev 00005 // Contact: mcseem@antigrain.com 00006 // mcseemagg@yahoo.com 00007 // http://antigrain.com 00008 // 00009 // AGG is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU General Public License 00011 // as published by the Free Software Foundation; either version 2 00012 // of the License, or (at your option) any later version. 00013 // 00014 // AGG is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with AGG; if not, write to the Free Software 00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00022 // MA 02110-1301, USA. 00023 //---------------------------------------------------------------------------- 00024 // 00025 // The Stack Blur Algorithm was invented by Mario Klingemann, 00026 // mario@quasimondo.com and described here: 00027 // http://incubator.quasimondo.com/processing/fast_blur_deluxe.php 00028 // (search phrase "Stackblur: Fast But Goodlooking"). 00029 // The major improvement is that there's no more division table 00030 // that was very expensive to create for large blur radii. Insted, 00031 // for 8-bit per channel and radius not exceeding 254 the division is 00032 // replaced by multiplication and shift. 00033 // 00034 //---------------------------------------------------------------------------- 00035 00036 #ifndef AGG_BLUR_INCLUDED 00037 #define AGG_BLUR_INCLUDED 00038 00039 #include "agg_array.h" 00040 #include "agg_pixfmt_transposer.h" 00041 00042 namespace agg 00043 { 00044 00045 template<class T> struct stack_blur_tables 00046 { 00047 static int16u const g_stack_blur8_mul[255]; 00048 static int8u const g_stack_blur8_shr[255]; 00049 }; 00050 00051 //------------------------------------------------------------------------ 00052 template<class T> 00053 int16u const stack_blur_tables<T>::g_stack_blur8_mul[255] = 00054 { 00055 512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512, 00056 454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512, 00057 482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456, 00058 437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512, 00059 497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328, 00060 320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456, 00061 446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335, 00062 329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512, 00063 505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405, 00064 399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328, 00065 324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271, 00066 268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456, 00067 451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388, 00068 385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335, 00069 332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292, 00070 289,287,285,282,280,278,275,273,271,269,267,265,263,261,259 00071 }; 00072 00073 //------------------------------------------------------------------------ 00074 template<class T> 00075 int8u const stack_blur_tables<T>::g_stack_blur8_shr[255] = 00076 { 00077 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 00078 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 00079 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 00080 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 00081 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 00082 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 00083 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 00084 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 00085 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 00086 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 00087 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 00088 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 00089 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 00090 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 00091 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 00092 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 00093 }; 00094 00095 00096 00097 //==============================================================stack_blur 00098 template<class ColorT, class CalculatorT> class stack_blur 00099 { 00100 public: 00101 typedef ColorT color_type; 00102 typedef CalculatorT calculator_type; 00103 00104 //-------------------------------------------------------------------- 00105 template<class Img> void blur_x(Img& img, unsigned radius) 00106 { 00107 if(radius < 1) return; 00108 00109 unsigned x, y, xp, i; 00110 unsigned stack_ptr; 00111 unsigned stack_start; 00112 00113 color_type pix; 00114 color_type* stack_pix; 00115 calculator_type sum; 00116 calculator_type sum_in; 00117 calculator_type sum_out; 00118 00119 unsigned w = img.width(); 00120 unsigned h = img.height(); 00121 unsigned wm = w - 1; 00122 unsigned div = radius * 2 + 1; 00123 00124 unsigned div_sum = (radius + 1) * (radius + 1); 00125 unsigned mul_sum = 0; 00126 unsigned shr_sum = 0; 00127 unsigned max_val = color_type::base_mask; 00128 00129 if(max_val <= 255 && radius < 255) 00130 { 00131 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[radius]; 00132 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[radius]; 00133 } 00134 00135 m_buf.allocate(w, 128); 00136 m_stack.allocate(div, 32); 00137 00138 for(y = 0; y < h; y++) 00139 { 00140 sum.clear(); 00141 sum_in.clear(); 00142 sum_out.clear(); 00143 00144 pix = img.pixel(0, y); 00145 for(i = 0; i <= radius; i++) 00146 { 00147 m_stack[i] = pix; 00148 sum.add(pix, i + 1); 00149 sum_out.add(pix); 00150 } 00151 for(i = 1; i <= radius; i++) 00152 { 00153 pix = img.pixel((i > wm) ? wm : i, y); 00154 m_stack[i + radius] = pix; 00155 sum.add(pix, radius + 1 - i); 00156 sum_in.add(pix); 00157 } 00158 00159 stack_ptr = radius; 00160 for(x = 0; x < w; x++) 00161 { 00162 if(mul_sum) sum.calc_pix(m_buf[x], mul_sum, shr_sum); 00163 else sum.calc_pix(m_buf[x], div_sum); 00164 00165 sum.sub(sum_out); 00166 00167 stack_start = stack_ptr + div - radius; 00168 if(stack_start >= div) stack_start -= div; 00169 stack_pix = &m_stack[stack_start]; 00170 00171 sum_out.sub(*stack_pix); 00172 00173 xp = x + radius + 1; 00174 if(xp > wm) xp = wm; 00175 pix = img.pixel(xp, y); 00176 00177 *stack_pix = pix; 00178 00179 sum_in.add(pix); 00180 sum.add(sum_in); 00181 00182 ++stack_ptr; 00183 if(stack_ptr >= div) stack_ptr = 0; 00184 stack_pix = &m_stack[stack_ptr]; 00185 00186 sum_out.add(*stack_pix); 00187 sum_in.sub(*stack_pix); 00188 } 00189 img.copy_color_hspan(0, y, w, &m_buf[0]); 00190 } 00191 } 00192 00193 //-------------------------------------------------------------------- 00194 template<class Img> void blur_y(Img& img, unsigned radius) 00195 { 00196 pixfmt_transposer<Img> img2(img); 00197 blur_x(img2, radius); 00198 } 00199 00200 //-------------------------------------------------------------------- 00201 template<class Img> void blur(Img& img, unsigned radius) 00202 { 00203 blur_x(img, radius); 00204 pixfmt_transposer<Img> img2(img); 00205 blur_x(img2, radius); 00206 } 00207 00208 private: 00209 pod_vector<color_type> m_buf; 00210 pod_vector<color_type> m_stack; 00211 }; 00212 00213 //====================================================stack_blur_calc_rgba 00214 template<class T=unsigned> struct stack_blur_calc_rgba 00215 { 00216 typedef T value_type; 00217 value_type r,g,b,a; 00218 00219 AGG_INLINE void clear() 00220 { 00221 r = g = b = a = 0; 00222 } 00223 00224 template<class ArgT> AGG_INLINE void add(const ArgT& v) 00225 { 00226 r += v.r; 00227 g += v.g; 00228 b += v.b; 00229 a += v.a; 00230 } 00231 00232 template<class ArgT> AGG_INLINE void add(const ArgT& v, unsigned k) 00233 { 00234 r += v.r * k; 00235 g += v.g * k; 00236 b += v.b * k; 00237 a += v.a * k; 00238 } 00239 00240 template<class ArgT> AGG_INLINE void sub(const ArgT& v) 00241 { 00242 r -= v.r; 00243 g -= v.g; 00244 b -= v.b; 00245 a -= v.a; 00246 } 00247 00248 template<class ArgT> AGG_INLINE void calc_pix(ArgT& v, unsigned div) 00249 { 00250 typedef typename ArgT::value_type value_type; 00251 v.r = value_type(r / div); 00252 v.g = value_type(g / div); 00253 v.b = value_type(b / div); 00254 v.a = value_type(a / div); 00255 } 00256 00257 template<class ArgT> 00258 AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr) 00259 { 00260 typedef typename ArgT::value_type value_type; 00261 v.r = value_type((r * mul) >> shr); 00262 v.g = value_type((g * mul) >> shr); 00263 v.b = value_type((b * mul) >> shr); 00264 v.a = value_type((a * mul) >> shr); 00265 } 00266 }; 00267 00268 00269 //=====================================================stack_blur_calc_rgb 00270 template<class T=unsigned> struct stack_blur_calc_rgb 00271 { 00272 typedef T value_type; 00273 value_type r,g,b; 00274 00275 AGG_INLINE void clear() 00276 { 00277 r = g = b = 0; 00278 } 00279 00280 template<class ArgT> AGG_INLINE void add(const ArgT& v) 00281 { 00282 r += v.r; 00283 g += v.g; 00284 b += v.b; 00285 } 00286 00287 template<class ArgT> AGG_INLINE void add(const ArgT& v, unsigned k) 00288 { 00289 r += v.r * k; 00290 g += v.g * k; 00291 b += v.b * k; 00292 } 00293 00294 template<class ArgT> AGG_INLINE void sub(const ArgT& v) 00295 { 00296 r -= v.r; 00297 g -= v.g; 00298 b -= v.b; 00299 } 00300 00301 template<class ArgT> AGG_INLINE void calc_pix(ArgT& v, unsigned div) 00302 { 00303 typedef typename ArgT::value_type value_type; 00304 v.r = value_type(r / div); 00305 v.g = value_type(g / div); 00306 v.b = value_type(b / div); 00307 } 00308 00309 template<class ArgT> 00310 AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr) 00311 { 00312 typedef typename ArgT::value_type value_type; 00313 v.r = value_type((r * mul) >> shr); 00314 v.g = value_type((g * mul) >> shr); 00315 v.b = value_type((b * mul) >> shr); 00316 } 00317 }; 00318 00319 00320 //====================================================stack_blur_calc_gray 00321 template<class T=unsigned> struct stack_blur_calc_gray 00322 { 00323 typedef T value_type; 00324 value_type v; 00325 00326 AGG_INLINE void clear() 00327 { 00328 v = 0; 00329 } 00330 00331 template<class ArgT> AGG_INLINE void add(const ArgT& a) 00332 { 00333 v += a.v; 00334 } 00335 00336 template<class ArgT> AGG_INLINE void add(const ArgT& a, unsigned k) 00337 { 00338 v += a.v * k; 00339 } 00340 00341 template<class ArgT> AGG_INLINE void sub(const ArgT& a) 00342 { 00343 v -= a.v; 00344 } 00345 00346 template<class ArgT> AGG_INLINE void calc_pix(ArgT& a, unsigned div) 00347 { 00348 typedef typename ArgT::value_type value_type; 00349 a.v = value_type(v / div); 00350 } 00351 00352 template<class ArgT> 00353 AGG_INLINE void calc_pix(ArgT& a, unsigned mul, unsigned shr) 00354 { 00355 typedef typename ArgT::value_type value_type; 00356 a.v = value_type((v * mul) >> shr); 00357 } 00358 }; 00359 00360 00361 00362 //========================================================stack_blur_gray8 00363 template<class Img> 00364 void stack_blur_gray8(Img& img, unsigned rx, unsigned ry) 00365 { 00366 unsigned x, y, xp, yp, i; 00367 unsigned stack_ptr; 00368 unsigned stack_start; 00369 00370 const int8u* src_pix_ptr; 00371 int8u* dst_pix_ptr; 00372 unsigned pix; 00373 unsigned stack_pix; 00374 unsigned sum; 00375 unsigned sum_in; 00376 unsigned sum_out; 00377 00378 unsigned w = img.width(); 00379 unsigned h = img.height(); 00380 unsigned wm = w - 1; 00381 unsigned hm = h - 1; 00382 00383 unsigned div; 00384 unsigned mul_sum; 00385 unsigned shr_sum; 00386 00387 pod_vector<int8u> stack; 00388 00389 if(rx > 0) 00390 { 00391 if(rx > 254) rx = 254; 00392 div = rx * 2 + 1; 00393 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx]; 00394 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx]; 00395 stack.allocate(div); 00396 00397 for(y = 0; y < h; y++) 00398 { 00399 sum = sum_in = sum_out = 0; 00400 00401 src_pix_ptr = img.pix_ptr(0, y); 00402 pix = *src_pix_ptr; 00403 for(i = 0; i <= rx; i++) 00404 { 00405 stack[i] = pix; 00406 sum += pix * (i + 1); 00407 sum_out += pix; 00408 } 00409 for(i = 1; i <= rx; i++) 00410 { 00411 if(i <= wm) src_pix_ptr += Img::pix_step; 00412 pix = *src_pix_ptr; 00413 stack[i + rx] = pix; 00414 sum += pix * (rx + 1 - i); 00415 sum_in += pix; 00416 } 00417 00418 stack_ptr = rx; 00419 xp = rx; 00420 if(xp > wm) xp = wm; 00421 src_pix_ptr = img.pix_ptr(xp, y); 00422 dst_pix_ptr = img.pix_ptr(0, y); 00423 for(x = 0; x < w; x++) 00424 { 00425 *dst_pix_ptr = (sum * mul_sum) >> shr_sum; 00426 dst_pix_ptr += Img::pix_step; 00427 00428 sum -= sum_out; 00429 00430 stack_start = stack_ptr + div - rx; 00431 if(stack_start >= div) stack_start -= div; 00432 sum_out -= stack[stack_start]; 00433 00434 if(xp < wm) 00435 { 00436 src_pix_ptr += Img::pix_step; 00437 pix = *src_pix_ptr; 00438 ++xp; 00439 } 00440 00441 stack[stack_start] = pix; 00442 00443 sum_in += pix; 00444 sum += sum_in; 00445 00446 ++stack_ptr; 00447 if(stack_ptr >= div) stack_ptr = 0; 00448 stack_pix = stack[stack_ptr]; 00449 00450 sum_out += stack_pix; 00451 sum_in -= stack_pix; 00452 } 00453 } 00454 } 00455 00456 if(ry > 0) 00457 { 00458 if(ry > 254) ry = 254; 00459 div = ry * 2 + 1; 00460 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry]; 00461 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry]; 00462 stack.allocate(div); 00463 00464 int stride = img.stride(); 00465 for(x = 0; x < w; x++) 00466 { 00467 sum = sum_in = sum_out = 0; 00468 00469 src_pix_ptr = img.pix_ptr(x, 0); 00470 pix = *src_pix_ptr; 00471 for(i = 0; i <= ry; i++) 00472 { 00473 stack[i] = pix; 00474 sum += pix * (i + 1); 00475 sum_out += pix; 00476 } 00477 for(i = 1; i <= ry; i++) 00478 { 00479 if(i <= hm) src_pix_ptr += stride; 00480 pix = *src_pix_ptr; 00481 stack[i + ry] = pix; 00482 sum += pix * (ry + 1 - i); 00483 sum_in += pix; 00484 } 00485 00486 stack_ptr = ry; 00487 yp = ry; 00488 if(yp > hm) yp = hm; 00489 src_pix_ptr = img.pix_ptr(x, yp); 00490 dst_pix_ptr = img.pix_ptr(x, 0); 00491 for(y = 0; y < h; y++) 00492 { 00493 *dst_pix_ptr = (sum * mul_sum) >> shr_sum; 00494 dst_pix_ptr += stride; 00495 00496 sum -= sum_out; 00497 00498 stack_start = stack_ptr + div - ry; 00499 if(stack_start >= div) stack_start -= div; 00500 sum_out -= stack[stack_start]; 00501 00502 if(yp < hm) 00503 { 00504 src_pix_ptr += stride; 00505 pix = *src_pix_ptr; 00506 ++yp; 00507 } 00508 00509 stack[stack_start] = pix; 00510 00511 sum_in += pix; 00512 sum += sum_in; 00513 00514 ++stack_ptr; 00515 if(stack_ptr >= div) stack_ptr = 0; 00516 stack_pix = stack[stack_ptr]; 00517 00518 sum_out += stack_pix; 00519 sum_in -= stack_pix; 00520 } 00521 } 00522 } 00523 } 00524 00525 00526 00527 //========================================================stack_blur_rgb24 00528 template<class Img> 00529 void stack_blur_rgb24(Img& img, unsigned rx, unsigned ry) 00530 { 00531 typedef typename Img::color_type color_type; 00532 typedef typename Img::order_type order_type; 00533 enum order_e 00534 { 00535 R = order_type::R, 00536 G = order_type::G, 00537 B = order_type::B 00538 }; 00539 00540 unsigned x, y, xp, yp, i; 00541 unsigned stack_ptr; 00542 unsigned stack_start; 00543 00544 const int8u* src_pix_ptr; 00545 int8u* dst_pix_ptr; 00546 color_type* stack_pix_ptr; 00547 00548 unsigned sum_r; 00549 unsigned sum_g; 00550 unsigned sum_b; 00551 unsigned sum_in_r; 00552 unsigned sum_in_g; 00553 unsigned sum_in_b; 00554 unsigned sum_out_r; 00555 unsigned sum_out_g; 00556 unsigned sum_out_b; 00557 00558 unsigned w = img.width(); 00559 unsigned h = img.height(); 00560 unsigned wm = w - 1; 00561 unsigned hm = h - 1; 00562 00563 unsigned div; 00564 unsigned mul_sum; 00565 unsigned shr_sum; 00566 00567 pod_vector<color_type> stack; 00568 00569 if(rx > 0) 00570 { 00571 if(rx > 254) rx = 254; 00572 div = rx * 2 + 1; 00573 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx]; 00574 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx]; 00575 stack.allocate(div); 00576 00577 for(y = 0; y < h; y++) 00578 { 00579 sum_r = 00580 sum_g = 00581 sum_b = 00582 sum_in_r = 00583 sum_in_g = 00584 sum_in_b = 00585 sum_out_r = 00586 sum_out_g = 00587 sum_out_b = 0; 00588 00589 src_pix_ptr = img.pix_ptr(0, y); 00590 for(i = 0; i <= rx; i++) 00591 { 00592 stack_pix_ptr = &stack[i]; 00593 stack_pix_ptr->r = src_pix_ptr[R]; 00594 stack_pix_ptr->g = src_pix_ptr[G]; 00595 stack_pix_ptr->b = src_pix_ptr[B]; 00596 sum_r += src_pix_ptr[R] * (i + 1); 00597 sum_g += src_pix_ptr[G] * (i + 1); 00598 sum_b += src_pix_ptr[B] * (i + 1); 00599 sum_out_r += src_pix_ptr[R]; 00600 sum_out_g += src_pix_ptr[G]; 00601 sum_out_b += src_pix_ptr[B]; 00602 } 00603 for(i = 1; i <= rx; i++) 00604 { 00605 if(i <= wm) src_pix_ptr += Img::pix_width; 00606 stack_pix_ptr = &stack[i + rx]; 00607 stack_pix_ptr->r = src_pix_ptr[R]; 00608 stack_pix_ptr->g = src_pix_ptr[G]; 00609 stack_pix_ptr->b = src_pix_ptr[B]; 00610 sum_r += src_pix_ptr[R] * (rx + 1 - i); 00611 sum_g += src_pix_ptr[G] * (rx + 1 - i); 00612 sum_b += src_pix_ptr[B] * (rx + 1 - i); 00613 sum_in_r += src_pix_ptr[R]; 00614 sum_in_g += src_pix_ptr[G]; 00615 sum_in_b += src_pix_ptr[B]; 00616 } 00617 00618 stack_ptr = rx; 00619 xp = rx; 00620 if(xp > wm) xp = wm; 00621 src_pix_ptr = img.pix_ptr(xp, y); 00622 dst_pix_ptr = img.pix_ptr(0, y); 00623 for(x = 0; x < w; x++) 00624 { 00625 dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; 00626 dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; 00627 dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; 00628 dst_pix_ptr += Img::pix_width; 00629 00630 sum_r -= sum_out_r; 00631 sum_g -= sum_out_g; 00632 sum_b -= sum_out_b; 00633 00634 stack_start = stack_ptr + div - rx; 00635 if(stack_start >= div) stack_start -= div; 00636 stack_pix_ptr = &stack[stack_start]; 00637 00638 sum_out_r -= stack_pix_ptr->r; 00639 sum_out_g -= stack_pix_ptr->g; 00640 sum_out_b -= stack_pix_ptr->b; 00641 00642 if(xp < wm) 00643 { 00644 src_pix_ptr += Img::pix_width; 00645 ++xp; 00646 } 00647 00648 stack_pix_ptr->r = src_pix_ptr[R]; 00649 stack_pix_ptr->g = src_pix_ptr[G]; 00650 stack_pix_ptr->b = src_pix_ptr[B]; 00651 00652 sum_in_r += src_pix_ptr[R]; 00653 sum_in_g += src_pix_ptr[G]; 00654 sum_in_b += src_pix_ptr[B]; 00655 sum_r += sum_in_r; 00656 sum_g += sum_in_g; 00657 sum_b += sum_in_b; 00658 00659 ++stack_ptr; 00660 if(stack_ptr >= div) stack_ptr = 0; 00661 stack_pix_ptr = &stack[stack_ptr]; 00662 00663 sum_out_r += stack_pix_ptr->r; 00664 sum_out_g += stack_pix_ptr->g; 00665 sum_out_b += stack_pix_ptr->b; 00666 sum_in_r -= stack_pix_ptr->r; 00667 sum_in_g -= stack_pix_ptr->g; 00668 sum_in_b -= stack_pix_ptr->b; 00669 } 00670 } 00671 } 00672 00673 if(ry > 0) 00674 { 00675 if(ry > 254) ry = 254; 00676 div = ry * 2 + 1; 00677 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry]; 00678 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry]; 00679 stack.allocate(div); 00680 00681 int stride = img.stride(); 00682 for(x = 0; x < w; x++) 00683 { 00684 sum_r = 00685 sum_g = 00686 sum_b = 00687 sum_in_r = 00688 sum_in_g = 00689 sum_in_b = 00690 sum_out_r = 00691 sum_out_g = 00692 sum_out_b = 0; 00693 00694 src_pix_ptr = img.pix_ptr(x, 0); 00695 for(i = 0; i <= ry; i++) 00696 { 00697 stack_pix_ptr = &stack[i]; 00698 stack_pix_ptr->r = src_pix_ptr[R]; 00699 stack_pix_ptr->g = src_pix_ptr[G]; 00700 stack_pix_ptr->b = src_pix_ptr[B]; 00701 sum_r += src_pix_ptr[R] * (i + 1); 00702 sum_g += src_pix_ptr[G] * (i + 1); 00703 sum_b += src_pix_ptr[B] * (i + 1); 00704 sum_out_r += src_pix_ptr[R]; 00705 sum_out_g += src_pix_ptr[G]; 00706 sum_out_b += src_pix_ptr[B]; 00707 } 00708 for(i = 1; i <= ry; i++) 00709 { 00710 if(i <= hm) src_pix_ptr += stride; 00711 stack_pix_ptr = &stack[i + ry]; 00712 stack_pix_ptr->r = src_pix_ptr[R]; 00713 stack_pix_ptr->g = src_pix_ptr[G]; 00714 stack_pix_ptr->b = src_pix_ptr[B]; 00715 sum_r += src_pix_ptr[R] * (ry + 1 - i); 00716 sum_g += src_pix_ptr[G] * (ry + 1 - i); 00717 sum_b += src_pix_ptr[B] * (ry + 1 - i); 00718 sum_in_r += src_pix_ptr[R]; 00719 sum_in_g += src_pix_ptr[G]; 00720 sum_in_b += src_pix_ptr[B]; 00721 } 00722 00723 stack_ptr = ry; 00724 yp = ry; 00725 if(yp > hm) yp = hm; 00726 src_pix_ptr = img.pix_ptr(x, yp); 00727 dst_pix_ptr = img.pix_ptr(x, 0); 00728 for(y = 0; y < h; y++) 00729 { 00730 dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; 00731 dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; 00732 dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; 00733 dst_pix_ptr += stride; 00734 00735 sum_r -= sum_out_r; 00736 sum_g -= sum_out_g; 00737 sum_b -= sum_out_b; 00738 00739 stack_start = stack_ptr + div - ry; 00740 if(stack_start >= div) stack_start -= div; 00741 00742 stack_pix_ptr = &stack[stack_start]; 00743 sum_out_r -= stack_pix_ptr->r; 00744 sum_out_g -= stack_pix_ptr->g; 00745 sum_out_b -= stack_pix_ptr->b; 00746 00747 if(yp < hm) 00748 { 00749 src_pix_ptr += stride; 00750 ++yp; 00751 } 00752 00753 stack_pix_ptr->r = src_pix_ptr[R]; 00754 stack_pix_ptr->g = src_pix_ptr[G]; 00755 stack_pix_ptr->b = src_pix_ptr[B]; 00756 00757 sum_in_r += src_pix_ptr[R]; 00758 sum_in_g += src_pix_ptr[G]; 00759 sum_in_b += src_pix_ptr[B]; 00760 sum_r += sum_in_r; 00761 sum_g += sum_in_g; 00762 sum_b += sum_in_b; 00763 00764 ++stack_ptr; 00765 if(stack_ptr >= div) stack_ptr = 0; 00766 stack_pix_ptr = &stack[stack_ptr]; 00767 00768 sum_out_r += stack_pix_ptr->r; 00769 sum_out_g += stack_pix_ptr->g; 00770 sum_out_b += stack_pix_ptr->b; 00771 sum_in_r -= stack_pix_ptr->r; 00772 sum_in_g -= stack_pix_ptr->g; 00773 sum_in_b -= stack_pix_ptr->b; 00774 } 00775 } 00776 } 00777 } 00778 00779 00780 00781 //=======================================================stack_blur_rgba32 00782 template<class Img> 00783 void stack_blur_rgba32(Img& img, unsigned rx, unsigned ry) 00784 { 00785 typedef typename Img::color_type color_type; 00786 typedef typename Img::order_type order_type; 00787 enum order_e 00788 { 00789 R = order_type::R, 00790 G = order_type::G, 00791 B = order_type::B, 00792 A = order_type::A 00793 }; 00794 00795 unsigned x, y, xp, yp, i; 00796 unsigned stack_ptr; 00797 unsigned stack_start; 00798 00799 const int8u* src_pix_ptr; 00800 int8u* dst_pix_ptr; 00801 color_type* stack_pix_ptr; 00802 00803 unsigned sum_r; 00804 unsigned sum_g; 00805 unsigned sum_b; 00806 unsigned sum_a; 00807 unsigned sum_in_r; 00808 unsigned sum_in_g; 00809 unsigned sum_in_b; 00810 unsigned sum_in_a; 00811 unsigned sum_out_r; 00812 unsigned sum_out_g; 00813 unsigned sum_out_b; 00814 unsigned sum_out_a; 00815 00816 unsigned w = img.width(); 00817 unsigned h = img.height(); 00818 unsigned wm = w - 1; 00819 unsigned hm = h - 1; 00820 00821 unsigned div; 00822 unsigned mul_sum; 00823 unsigned shr_sum; 00824 00825 pod_vector<color_type> stack; 00826 00827 if(rx > 0) 00828 { 00829 if(rx > 254) rx = 254; 00830 div = rx * 2 + 1; 00831 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx]; 00832 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx]; 00833 stack.allocate(div); 00834 00835 for(y = 0; y < h; y++) 00836 { 00837 sum_r = 00838 sum_g = 00839 sum_b = 00840 sum_a = 00841 sum_in_r = 00842 sum_in_g = 00843 sum_in_b = 00844 sum_in_a = 00845 sum_out_r = 00846 sum_out_g = 00847 sum_out_b = 00848 sum_out_a = 0; 00849 00850 src_pix_ptr = img.pix_ptr(0, y); 00851 for(i = 0; i <= rx; i++) 00852 { 00853 stack_pix_ptr = &stack[i]; 00854 stack_pix_ptr->r = src_pix_ptr[R]; 00855 stack_pix_ptr->g = src_pix_ptr[G]; 00856 stack_pix_ptr->b = src_pix_ptr[B]; 00857 stack_pix_ptr->a = src_pix_ptr[A]; 00858 sum_r += src_pix_ptr[R] * (i + 1); 00859 sum_g += src_pix_ptr[G] * (i + 1); 00860 sum_b += src_pix_ptr[B] * (i + 1); 00861 sum_a += src_pix_ptr[A] * (i + 1); 00862 sum_out_r += src_pix_ptr[R]; 00863 sum_out_g += src_pix_ptr[G]; 00864 sum_out_b += src_pix_ptr[B]; 00865 sum_out_a += src_pix_ptr[A]; 00866 } 00867 for(i = 1; i <= rx; i++) 00868 { 00869 if(i <= wm) src_pix_ptr += Img::pix_width; 00870 stack_pix_ptr = &stack[i + rx]; 00871 stack_pix_ptr->r = src_pix_ptr[R]; 00872 stack_pix_ptr->g = src_pix_ptr[G]; 00873 stack_pix_ptr->b = src_pix_ptr[B]; 00874 stack_pix_ptr->a = src_pix_ptr[A]; 00875 sum_r += src_pix_ptr[R] * (rx + 1 - i); 00876 sum_g += src_pix_ptr[G] * (rx + 1 - i); 00877 sum_b += src_pix_ptr[B] * (rx + 1 - i); 00878 sum_a += src_pix_ptr[A] * (rx + 1 - i); 00879 sum_in_r += src_pix_ptr[R]; 00880 sum_in_g += src_pix_ptr[G]; 00881 sum_in_b += src_pix_ptr[B]; 00882 sum_in_a += src_pix_ptr[A]; 00883 } 00884 00885 stack_ptr = rx; 00886 xp = rx; 00887 if(xp > wm) xp = wm; 00888 src_pix_ptr = img.pix_ptr(xp, y); 00889 dst_pix_ptr = img.pix_ptr(0, y); 00890 for(x = 0; x < w; x++) 00891 { 00892 dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; 00893 dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; 00894 dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; 00895 dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum; 00896 dst_pix_ptr += Img::pix_width; 00897 00898 sum_r -= sum_out_r; 00899 sum_g -= sum_out_g; 00900 sum_b -= sum_out_b; 00901 sum_a -= sum_out_a; 00902 00903 stack_start = stack_ptr + div - rx; 00904 if(stack_start >= div) stack_start -= div; 00905 stack_pix_ptr = &stack[stack_start]; 00906 00907 sum_out_r -= stack_pix_ptr->r; 00908 sum_out_g -= stack_pix_ptr->g; 00909 sum_out_b -= stack_pix_ptr->b; 00910 sum_out_a -= stack_pix_ptr->a; 00911 00912 if(xp < wm) 00913 { 00914 src_pix_ptr += Img::pix_width; 00915 ++xp; 00916 } 00917 00918 stack_pix_ptr->r = src_pix_ptr[R]; 00919 stack_pix_ptr->g = src_pix_ptr[G]; 00920 stack_pix_ptr->b = src_pix_ptr[B]; 00921 stack_pix_ptr->a = src_pix_ptr[A]; 00922 00923 sum_in_r += src_pix_ptr[R]; 00924 sum_in_g += src_pix_ptr[G]; 00925 sum_in_b += src_pix_ptr[B]; 00926 sum_in_a += src_pix_ptr[A]; 00927 sum_r += sum_in_r; 00928 sum_g += sum_in_g; 00929 sum_b += sum_in_b; 00930 sum_a += sum_in_a; 00931 00932 ++stack_ptr; 00933 if(stack_ptr >= div) stack_ptr = 0; 00934 stack_pix_ptr = &stack[stack_ptr]; 00935 00936 sum_out_r += stack_pix_ptr->r; 00937 sum_out_g += stack_pix_ptr->g; 00938 sum_out_b += stack_pix_ptr->b; 00939 sum_out_a += stack_pix_ptr->a; 00940 sum_in_r -= stack_pix_ptr->r; 00941 sum_in_g -= stack_pix_ptr->g; 00942 sum_in_b -= stack_pix_ptr->b; 00943 sum_in_a -= stack_pix_ptr->a; 00944 } 00945 } 00946 } 00947 00948 if(ry > 0) 00949 { 00950 if(ry > 254) ry = 254; 00951 div = ry * 2 + 1; 00952 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry]; 00953 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry]; 00954 stack.allocate(div); 00955 00956 int stride = img.stride(); 00957 for(x = 0; x < w; x++) 00958 { 00959 sum_r = 00960 sum_g = 00961 sum_b = 00962 sum_a = 00963 sum_in_r = 00964 sum_in_g = 00965 sum_in_b = 00966 sum_in_a = 00967 sum_out_r = 00968 sum_out_g = 00969 sum_out_b = 00970 sum_out_a = 0; 00971 00972 src_pix_ptr = img.pix_ptr(x, 0); 00973 for(i = 0; i <= ry; i++) 00974 { 00975 stack_pix_ptr = &stack[i]; 00976 stack_pix_ptr->r = src_pix_ptr[R]; 00977 stack_pix_ptr->g = src_pix_ptr[G]; 00978 stack_pix_ptr->b = src_pix_ptr[B]; 00979 stack_pix_ptr->a = src_pix_ptr[A]; 00980 sum_r += src_pix_ptr[R] * (i + 1); 00981 sum_g += src_pix_ptr[G] * (i + 1); 00982 sum_b += src_pix_ptr[B] * (i + 1); 00983 sum_a += src_pix_ptr[A] * (i + 1); 00984 sum_out_r += src_pix_ptr[R]; 00985 sum_out_g += src_pix_ptr[G]; 00986 sum_out_b += src_pix_ptr[B]; 00987 sum_out_a += src_pix_ptr[A]; 00988 } 00989 for(i = 1; i <= ry; i++) 00990 { 00991 if(i <= hm) src_pix_ptr += stride; 00992 stack_pix_ptr = &stack[i + ry]; 00993 stack_pix_ptr->r = src_pix_ptr[R]; 00994 stack_pix_ptr->g = src_pix_ptr[G]; 00995 stack_pix_ptr->b = src_pix_ptr[B]; 00996 stack_pix_ptr->a = src_pix_ptr[A]; 00997 sum_r += src_pix_ptr[R] * (ry + 1 - i); 00998 sum_g += src_pix_ptr[G] * (ry + 1 - i); 00999 sum_b += src_pix_ptr[B] * (ry + 1 - i); 01000 sum_a += src_pix_ptr[A] * (ry + 1 - i); 01001 sum_in_r += src_pix_ptr[R]; 01002 sum_in_g += src_pix_ptr[G]; 01003 sum_in_b += src_pix_ptr[B]; 01004 sum_in_a += src_pix_ptr[A]; 01005 } 01006 01007 stack_ptr = ry; 01008 yp = ry; 01009 if(yp > hm) yp = hm; 01010 src_pix_ptr = img.pix_ptr(x, yp); 01011 dst_pix_ptr = img.pix_ptr(x, 0); 01012 for(y = 0; y < h; y++) 01013 { 01014 dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; 01015 dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; 01016 dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; 01017 dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum; 01018 dst_pix_ptr += stride; 01019 01020 sum_r -= sum_out_r; 01021 sum_g -= sum_out_g; 01022 sum_b -= sum_out_b; 01023 sum_a -= sum_out_a; 01024 01025 stack_start = stack_ptr + div - ry; 01026 if(stack_start >= div) stack_start -= div; 01027 01028 stack_pix_ptr = &stack[stack_start]; 01029 sum_out_r -= stack_pix_ptr->r; 01030 sum_out_g -= stack_pix_ptr->g; 01031 sum_out_b -= stack_pix_ptr->b; 01032 sum_out_a -= stack_pix_ptr->a; 01033 01034 if(yp < hm) 01035 { 01036 src_pix_ptr += stride; 01037 ++yp; 01038 } 01039 01040 stack_pix_ptr->r = src_pix_ptr[R]; 01041 stack_pix_ptr->g = src_pix_ptr[G]; 01042 stack_pix_ptr->b = src_pix_ptr[B]; 01043 stack_pix_ptr->a = src_pix_ptr[A]; 01044 01045 sum_in_r += src_pix_ptr[R]; 01046 sum_in_g += src_pix_ptr[G]; 01047 sum_in_b += src_pix_ptr[B]; 01048 sum_in_a += src_pix_ptr[A]; 01049 sum_r += sum_in_r; 01050 sum_g += sum_in_g; 01051 sum_b += sum_in_b; 01052 sum_a += sum_in_a; 01053 01054 ++stack_ptr; 01055 if(stack_ptr >= div) stack_ptr = 0; 01056 stack_pix_ptr = &stack[stack_ptr]; 01057 01058 sum_out_r += stack_pix_ptr->r; 01059 sum_out_g += stack_pix_ptr->g; 01060 sum_out_b += stack_pix_ptr->b; 01061 sum_out_a += stack_pix_ptr->a; 01062 sum_in_r -= stack_pix_ptr->r; 01063 sum_in_g -= stack_pix_ptr->g; 01064 sum_in_b -= stack_pix_ptr->b; 01065 sum_in_a -= stack_pix_ptr->a; 01066 } 01067 } 01068 } 01069 } 01070 01071 01072 01073 //===========================================================recursive_blur 01074 template<class ColorT, class CalculatorT> class recursive_blur 01075 { 01076 public: 01077 typedef ColorT color_type; 01078 typedef CalculatorT calculator_type; 01079 typedef typename color_type::value_type value_type; 01080 typedef typename calculator_type::value_type calc_type; 01081 01082 //-------------------------------------------------------------------- 01083 template<class Img> void blur_x(Img& img, double radius) 01084 { 01085 if(radius < 0.62) return; 01086 if(img.width() < 3) return; 01087 01088 calc_type s = calc_type(radius * 0.5); 01089 calc_type q = calc_type((s < 2.5) ? 01090 3.97156 - 4.14554 * sqrt(1 - 0.26891 * s) : 01091 0.98711 * s - 0.96330); 01092 01093 calc_type q2 = calc_type(q * q); 01094 calc_type q3 = calc_type(q2 * q); 01095 01096 calc_type b0 = calc_type(1.0 / (1.578250 + 01097 2.444130 * q + 01098 1.428100 * q2 + 01099 0.422205 * q3)); 01100 01101 calc_type b1 = calc_type( 2.44413 * q + 01102 2.85619 * q2 + 01103 1.26661 * q3); 01104 01105 calc_type b2 = calc_type(-1.42810 * q2 + 01106 -1.26661 * q3); 01107 01108 calc_type b3 = calc_type(0.422205 * q3); 01109 01110 calc_type b = calc_type(1 - (b1 + b2 + b3) * b0); 01111 01112 b1 *= b0; 01113 b2 *= b0; 01114 b3 *= b0; 01115 01116 int w = img.width(); 01117 int h = img.height(); 01118 int wm = w-1; 01119 int x, y; 01120 01121 m_sum1.allocate(w); 01122 m_sum2.allocate(w); 01123 m_buf.allocate(w); 01124 01125 for(y = 0; y < h; y++) 01126 { 01127 calculator_type c; 01128 c.from_pix(img.pixel(0, y)); 01129 m_sum1[0].calc(b, b1, b2, b3, c, c, c, c); 01130 c.from_pix(img.pixel(1, y)); 01131 m_sum1[1].calc(b, b1, b2, b3, c, m_sum1[0], m_sum1[0], m_sum1[0]); 01132 c.from_pix(img.pixel(2, y)); 01133 m_sum1[2].calc(b, b1, b2, b3, c, m_sum1[1], m_sum1[0], m_sum1[0]); 01134 01135 for(x = 3; x < w; ++x) 01136 { 01137 c.from_pix(img.pixel(x, y)); 01138 m_sum1[x].calc(b, b1, b2, b3, c, m_sum1[x-1], m_sum1[x-2], m_sum1[x-3]); 01139 } 01140 01141 m_sum2[wm ].calc(b, b1, b2, b3, m_sum1[wm ], m_sum1[wm ], m_sum1[wm], m_sum1[wm]); 01142 m_sum2[wm-1].calc(b, b1, b2, b3, m_sum1[wm-1], m_sum2[wm ], m_sum2[wm], m_sum2[wm]); 01143 m_sum2[wm-2].calc(b, b1, b2, b3, m_sum1[wm-2], m_sum2[wm-1], m_sum2[wm], m_sum2[wm]); 01144 m_sum2[wm ].to_pix(m_buf[wm ]); 01145 m_sum2[wm-1].to_pix(m_buf[wm-1]); 01146 m_sum2[wm-2].to_pix(m_buf[wm-2]); 01147 01148 for(x = wm-3; x >= 0; --x) 01149 { 01150 m_sum2[x].calc(b, b1, b2, b3, m_sum1[x], m_sum2[x+1], m_sum2[x+2], m_sum2[x+3]); 01151 m_sum2[x].to_pix(m_buf[x]); 01152 } 01153 img.copy_color_hspan(0, y, w, &m_buf[0]); 01154 } 01155 } 01156 01157 //-------------------------------------------------------------------- 01158 template<class Img> void blur_y(Img& img, double radius) 01159 { 01160 pixfmt_transposer<Img> img2(img); 01161 blur_x(img2, radius); 01162 } 01163 01164 //-------------------------------------------------------------------- 01165 template<class Img> void blur(Img& img, double radius) 01166 { 01167 blur_x(img, radius); 01168 pixfmt_transposer<Img> img2(img); 01169 blur_x(img2, radius); 01170 } 01171 01172 private: 01173 agg::pod_vector<calculator_type> m_sum1; 01174 agg::pod_vector<calculator_type> m_sum2; 01175 agg::pod_vector<color_type> m_buf; 01176 }; 01177 01178 01179 //=================================================recursive_blur_calc_rgba 01180 template<class T=double> struct recursive_blur_calc_rgba 01181 { 01182 typedef T value_type; 01183 typedef recursive_blur_calc_rgba<T> self_type; 01184 01185 value_type r,g,b,a; 01186 01187 template<class ColorT> 01188 AGG_INLINE void from_pix(const ColorT& c) 01189 { 01190 r = c.r; 01191 g = c.g; 01192 b = c.b; 01193 a = c.a; 01194 } 01195 01196 AGG_INLINE void calc(value_type b1, 01197 value_type b2, 01198 value_type b3, 01199 value_type b4, 01200 const self_type& c1, 01201 const self_type& c2, 01202 const self_type& c3, 01203 const self_type& c4) 01204 { 01205 r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r; 01206 g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g; 01207 b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b; 01208 a = b1*c1.a + b2*c2.a + b3*c3.a + b4*c4.a; 01209 } 01210 01211 template<class ColorT> 01212 AGG_INLINE void to_pix(ColorT& c) const 01213 { 01214 typedef typename ColorT::value_type cv_type; 01215 c.r = (cv_type)uround(r); 01216 c.g = (cv_type)uround(g); 01217 c.b = (cv_type)uround(b); 01218 c.a = (cv_type)uround(a); 01219 } 01220 }; 01221 01222 01223 //=================================================recursive_blur_calc_rgb 01224 template<class T=double> struct recursive_blur_calc_rgb 01225 { 01226 typedef T value_type; 01227 typedef recursive_blur_calc_rgb<T> self_type; 01228 01229 value_type r,g,b; 01230 01231 template<class ColorT> 01232 AGG_INLINE void from_pix(const ColorT& c) 01233 { 01234 r = c.r; 01235 g = c.g; 01236 b = c.b; 01237 } 01238 01239 AGG_INLINE void calc(value_type b1, 01240 value_type b2, 01241 value_type b3, 01242 value_type b4, 01243 const self_type& c1, 01244 const self_type& c2, 01245 const self_type& c3, 01246 const self_type& c4) 01247 { 01248 r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r; 01249 g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g; 01250 b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b; 01251 } 01252 01253 template<class ColorT> 01254 AGG_INLINE void to_pix(ColorT& c) const 01255 { 01256 typedef typename ColorT::value_type cv_type; 01257 c.r = (cv_type)uround(r); 01258 c.g = (cv_type)uround(g); 01259 c.b = (cv_type)uround(b); 01260 } 01261 }; 01262 01263 01264 //================================================recursive_blur_calc_gray 01265 template<class T=double> struct recursive_blur_calc_gray 01266 { 01267 typedef T value_type; 01268 typedef recursive_blur_calc_gray<T> self_type; 01269 01270 value_type v; 01271 01272 template<class ColorT> 01273 AGG_INLINE void from_pix(const ColorT& c) 01274 { 01275 v = c.v; 01276 } 01277 01278 AGG_INLINE void calc(value_type b1, 01279 value_type b2, 01280 value_type b3, 01281 value_type b4, 01282 const self_type& c1, 01283 const self_type& c2, 01284 const self_type& c3, 01285 const self_type& c4) 01286 { 01287 v = b1*c1.v + b2*c2.v + b3*c3.v + b4*c4.v; 01288 } 01289 01290 template<class ColorT> 01291 AGG_INLINE void to_pix(ColorT& c) const 01292 { 01293 typedef typename ColorT::value_type cv_type; 01294 c.v = (cv_type)uround(v); 01295 } 01296 }; 01297 01298 } 01299 01300 01301 01302 01303 #endif