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 // Adaptation for high precision colors has been sponsored by 00026 // Liberty Technology Systems, Inc., visit http://lib-sys.com 00027 // 00028 // Liberty Technology Systems, Inc. is the provider of 00029 // PostScript and PDF technology for software developers. 00030 // 00031 //---------------------------------------------------------------------------- 00032 #ifndef AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED 00033 #define AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED 00034 00035 #include "agg_basics.h" 00036 #include "agg_color_gray.h" 00037 #include "agg_span_image_filter.h" 00038 00039 00040 namespace agg 00041 { 00042 00043 //==============================================span_image_filter_gray_nn 00044 template<class Source, class Interpolator> 00045 class span_image_filter_gray_nn : 00046 public span_image_filter<Source, Interpolator> 00047 { 00048 public: 00049 typedef Source source_type; 00050 typedef typename source_type::color_type color_type; 00051 typedef Interpolator interpolator_type; 00052 typedef span_image_filter<source_type, interpolator_type> base_type; 00053 typedef typename color_type::value_type value_type; 00054 typedef typename color_type::calc_type calc_type; 00055 enum base_scale_e 00056 { 00057 base_shift = color_type::base_shift, 00058 base_mask = color_type::base_mask 00059 }; 00060 00061 //-------------------------------------------------------------------- 00062 span_image_filter_gray_nn() {} 00063 span_image_filter_gray_nn(source_type& src, 00064 interpolator_type& inter) : 00065 base_type(src, inter, 0) 00066 {} 00067 00068 //-------------------------------------------------------------------- 00069 void generate(color_type* span, int x, int y, unsigned len) 00070 { 00071 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 00072 y + base_type::filter_dy_dbl(), len); 00073 do 00074 { 00075 base_type::interpolator().coordinates(&x, &y); 00076 span->v = *(const value_type*) 00077 base_type::source().span(x >> image_subpixel_shift, 00078 y >> image_subpixel_shift, 00079 1); 00080 span->a = base_mask; 00081 ++span; 00082 ++base_type::interpolator(); 00083 } while(--len); 00084 } 00085 }; 00086 00087 00088 00089 //=========================================span_image_filter_gray_bilinear 00090 template<class Source, class Interpolator> 00091 class span_image_filter_gray_bilinear : 00092 public span_image_filter<Source, Interpolator> 00093 { 00094 public: 00095 typedef Source source_type; 00096 typedef typename source_type::color_type color_type; 00097 typedef Interpolator interpolator_type; 00098 typedef span_image_filter<source_type, interpolator_type> base_type; 00099 typedef typename color_type::value_type value_type; 00100 typedef typename color_type::calc_type calc_type; 00101 enum base_scale_e 00102 { 00103 base_shift = color_type::base_shift, 00104 base_mask = color_type::base_mask 00105 }; 00106 00107 //-------------------------------------------------------------------- 00108 span_image_filter_gray_bilinear() {} 00109 span_image_filter_gray_bilinear(source_type& src, 00110 interpolator_type& inter) : 00111 base_type(src, inter, 0) 00112 {} 00113 00114 00115 //-------------------------------------------------------------------- 00116 void generate(color_type* span, int x, int y, unsigned len) 00117 { 00118 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 00119 y + base_type::filter_dy_dbl(), len); 00120 calc_type fg; 00121 const value_type *fg_ptr; 00122 do 00123 { 00124 int x_hr; 00125 int y_hr; 00126 00127 base_type::interpolator().coordinates(&x_hr, &y_hr); 00128 00129 x_hr -= base_type::filter_dx_int(); 00130 y_hr -= base_type::filter_dy_int(); 00131 00132 int x_lr = x_hr >> image_subpixel_shift; 00133 int y_lr = y_hr >> image_subpixel_shift; 00134 00135 fg = image_subpixel_scale * image_subpixel_scale / 2; 00136 00137 x_hr &= image_subpixel_mask; 00138 y_hr &= image_subpixel_mask; 00139 00140 fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); 00141 fg += *fg_ptr * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); 00142 00143 fg_ptr = (const value_type*)base_type::source().next_x(); 00144 fg += *fg_ptr * x_hr * (image_subpixel_scale - y_hr); 00145 00146 fg_ptr = (const value_type*)base_type::source().next_y(); 00147 fg += *fg_ptr * (image_subpixel_scale - x_hr) * y_hr; 00148 00149 fg_ptr = (const value_type*)base_type::source().next_x(); 00150 fg += *fg_ptr * x_hr * y_hr; 00151 00152 span->v = value_type(fg >> (image_subpixel_shift * 2)); 00153 span->a = base_mask; 00154 ++span; 00155 ++base_type::interpolator(); 00156 00157 } while(--len); 00158 } 00159 }; 00160 00161 00162 //====================================span_image_filter_gray_bilinear_clip 00163 template<class Source, class Interpolator> 00164 class span_image_filter_gray_bilinear_clip : 00165 public span_image_filter<Source, Interpolator> 00166 { 00167 public: 00168 typedef Source source_type; 00169 typedef typename source_type::color_type color_type; 00170 typedef Interpolator interpolator_type; 00171 typedef span_image_filter<source_type, interpolator_type> base_type; 00172 typedef typename color_type::value_type value_type; 00173 typedef typename color_type::calc_type calc_type; 00174 enum base_scale_e 00175 { 00176 base_shift = color_type::base_shift, 00177 base_mask = color_type::base_mask 00178 }; 00179 00180 //-------------------------------------------------------------------- 00181 span_image_filter_gray_bilinear_clip() {} 00182 span_image_filter_gray_bilinear_clip(source_type& src, 00183 const color_type& back_color, 00184 interpolator_type& inter) : 00185 base_type(src, inter, 0), 00186 m_back_color(back_color) 00187 {} 00188 const color_type& background_color() const { return m_back_color; } 00189 void background_color(const color_type& v) { m_back_color = v; } 00190 00191 //-------------------------------------------------------------------- 00192 void generate(color_type* span, int x, int y, unsigned len) 00193 { 00194 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 00195 y + base_type::filter_dy_dbl(), len); 00196 calc_type fg; 00197 calc_type src_alpha; 00198 value_type back_v = m_back_color.v; 00199 value_type back_a = m_back_color.a; 00200 00201 const value_type *fg_ptr; 00202 00203 int maxx = base_type::source().width() - 1; 00204 int maxy = base_type::source().height() - 1; 00205 00206 do 00207 { 00208 int x_hr; 00209 int y_hr; 00210 00211 base_type::interpolator().coordinates(&x_hr, &y_hr); 00212 00213 x_hr -= base_type::filter_dx_int(); 00214 y_hr -= base_type::filter_dy_int(); 00215 00216 int x_lr = x_hr >> image_subpixel_shift; 00217 int y_lr = y_hr >> image_subpixel_shift; 00218 00219 if(x_lr >= 0 && y_lr >= 0 && 00220 x_lr < maxx && y_lr < maxy) 00221 { 00222 fg = image_subpixel_scale * image_subpixel_scale / 2; 00223 00224 x_hr &= image_subpixel_mask; 00225 y_hr &= image_subpixel_mask; 00226 fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr; 00227 00228 fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); 00229 fg += *fg_ptr++ * (image_subpixel_scale - y_hr) * x_hr; 00230 00231 ++y_lr; 00232 fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr; 00233 00234 fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * y_hr; 00235 fg += *fg_ptr++ * x_hr * y_hr; 00236 00237 fg >>= image_subpixel_shift * 2; 00238 src_alpha = base_mask; 00239 } 00240 else 00241 { 00242 unsigned weight; 00243 if(x_lr < -1 || y_lr < -1 || 00244 x_lr > maxx || y_lr > maxy) 00245 { 00246 fg = back_v; 00247 src_alpha = back_a; 00248 } 00249 else 00250 { 00251 fg = 00252 src_alpha = image_subpixel_scale * image_subpixel_scale / 2; 00253 00254 x_hr &= image_subpixel_mask; 00255 y_hr &= image_subpixel_mask; 00256 00257 weight = (image_subpixel_scale - x_hr) * 00258 (image_subpixel_scale - y_hr); 00259 if(x_lr >= 0 && y_lr >= 0 && 00260 x_lr <= maxx && y_lr <= maxy) 00261 { 00262 fg += weight * 00263 *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); 00264 src_alpha += weight * base_mask; 00265 } 00266 else 00267 { 00268 fg += back_v * weight; 00269 src_alpha += back_a * weight; 00270 } 00271 00272 x_lr++; 00273 00274 weight = x_hr * (image_subpixel_scale - y_hr); 00275 if(x_lr >= 0 && y_lr >= 0 && 00276 x_lr <= maxx && y_lr <= maxy) 00277 { 00278 fg += weight * 00279 *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); 00280 src_alpha += weight * base_mask; 00281 } 00282 else 00283 { 00284 fg += back_v * weight; 00285 src_alpha += back_a * weight; 00286 } 00287 00288 x_lr--; 00289 y_lr++; 00290 00291 weight = (image_subpixel_scale - x_hr) * y_hr; 00292 if(x_lr >= 0 && y_lr >= 0 && 00293 x_lr <= maxx && y_lr <= maxy) 00294 { 00295 fg += weight * 00296 *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); 00297 src_alpha += weight * base_mask; 00298 } 00299 else 00300 { 00301 fg += back_v * weight; 00302 src_alpha += back_a * weight; 00303 } 00304 00305 x_lr++; 00306 00307 weight = x_hr * y_hr; 00308 if(x_lr >= 0 && y_lr >= 0 && 00309 x_lr <= maxx && y_lr <= maxy) 00310 { 00311 fg += weight * 00312 *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); 00313 src_alpha += weight * base_mask; 00314 } 00315 else 00316 { 00317 fg += back_v * weight; 00318 src_alpha += back_a * weight; 00319 } 00320 00321 fg >>= image_subpixel_shift * 2; 00322 src_alpha >>= image_subpixel_shift * 2; 00323 } 00324 } 00325 00326 span->v = (value_type)fg; 00327 span->a = (value_type)src_alpha; 00328 ++span; 00329 ++base_type::interpolator(); 00330 00331 } while(--len); 00332 } 00333 private: 00334 color_type m_back_color; 00335 }; 00336 00337 00338 00339 //==============================================span_image_filter_gray_2x2 00340 template<class Source, class Interpolator> 00341 class span_image_filter_gray_2x2 : 00342 public span_image_filter<Source, Interpolator> 00343 { 00344 public: 00345 typedef Source source_type; 00346 typedef typename source_type::color_type color_type; 00347 typedef Interpolator interpolator_type; 00348 typedef span_image_filter<source_type, interpolator_type> base_type; 00349 typedef typename color_type::value_type value_type; 00350 typedef typename color_type::calc_type calc_type; 00351 enum base_scale_e 00352 { 00353 base_shift = color_type::base_shift, 00354 base_mask = color_type::base_mask 00355 }; 00356 00357 //-------------------------------------------------------------------- 00358 span_image_filter_gray_2x2() {} 00359 span_image_filter_gray_2x2(source_type& src, 00360 interpolator_type& inter, 00361 const image_filter_lut& filter) : 00362 base_type(src, inter, &filter) 00363 {} 00364 00365 00366 //-------------------------------------------------------------------- 00367 void generate(color_type* span, int x, int y, unsigned len) 00368 { 00369 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 00370 y + base_type::filter_dy_dbl(), len); 00371 00372 calc_type fg; 00373 00374 const value_type *fg_ptr; 00375 const int16* weight_array = base_type::filter().weight_array() + 00376 ((base_type::filter().diameter()/2 - 1) << 00377 image_subpixel_shift); 00378 do 00379 { 00380 int x_hr; 00381 int y_hr; 00382 00383 base_type::interpolator().coordinates(&x_hr, &y_hr); 00384 00385 x_hr -= base_type::filter_dx_int(); 00386 y_hr -= base_type::filter_dy_int(); 00387 00388 int x_lr = x_hr >> image_subpixel_shift; 00389 int y_lr = y_hr >> image_subpixel_shift; 00390 00391 unsigned weight; 00392 fg = image_filter_scale / 2; 00393 00394 x_hr &= image_subpixel_mask; 00395 y_hr &= image_subpixel_mask; 00396 00397 fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); 00398 weight = (weight_array[x_hr + image_subpixel_scale] * 00399 weight_array[y_hr + image_subpixel_scale] + 00400 image_filter_scale / 2) >> 00401 image_filter_shift; 00402 fg += weight * *fg_ptr; 00403 00404 fg_ptr = (const value_type*)base_type::source().next_x(); 00405 weight = (weight_array[x_hr] * 00406 weight_array[y_hr + image_subpixel_scale] + 00407 image_filter_scale / 2) >> 00408 image_filter_shift; 00409 fg += weight * *fg_ptr; 00410 00411 fg_ptr = (const value_type*)base_type::source().next_y(); 00412 weight = (weight_array[x_hr + image_subpixel_scale] * 00413 weight_array[y_hr] + 00414 image_filter_scale / 2) >> 00415 image_filter_shift; 00416 fg += weight * *fg_ptr; 00417 00418 fg_ptr = (const value_type*)base_type::source().next_x(); 00419 weight = (weight_array[x_hr] * 00420 weight_array[y_hr] + 00421 image_filter_scale / 2) >> 00422 image_filter_shift; 00423 fg += weight * *fg_ptr; 00424 00425 fg >>= image_filter_shift; 00426 if(fg > base_mask) fg = base_mask; 00427 00428 span->v = (value_type)fg; 00429 span->a = base_mask; 00430 ++span; 00431 ++base_type::interpolator(); 00432 } while(--len); 00433 } 00434 }; 00435 00436 00437 00438 //==================================================span_image_filter_gray 00439 template<class Source, class Interpolator> 00440 class span_image_filter_gray : 00441 public span_image_filter<Source, Interpolator> 00442 { 00443 public: 00444 typedef Source source_type; 00445 typedef typename source_type::color_type color_type; 00446 typedef Interpolator interpolator_type; 00447 typedef span_image_filter<source_type, interpolator_type> base_type; 00448 typedef typename color_type::value_type value_type; 00449 typedef typename color_type::calc_type calc_type; 00450 enum base_scale_e 00451 { 00452 base_shift = color_type::base_shift, 00453 base_mask = color_type::base_mask 00454 }; 00455 00456 //-------------------------------------------------------------------- 00457 span_image_filter_gray() {} 00458 span_image_filter_gray(source_type& src, 00459 interpolator_type& inter, 00460 const image_filter_lut& filter) : 00461 base_type(src, inter, &filter) 00462 {} 00463 00464 //-------------------------------------------------------------------- 00465 void generate(color_type* span, int x, int y, unsigned len) 00466 { 00467 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 00468 y + base_type::filter_dy_dbl(), len); 00469 00470 int fg; 00471 const value_type *fg_ptr; 00472 00473 unsigned diameter = base_type::filter().diameter(); 00474 int start = base_type::filter().start(); 00475 const int16* weight_array = base_type::filter().weight_array(); 00476 00477 int x_count; 00478 int weight_y; 00479 00480 do 00481 { 00482 base_type::interpolator().coordinates(&x, &y); 00483 00484 x -= base_type::filter_dx_int(); 00485 y -= base_type::filter_dy_int(); 00486 00487 int x_hr = x; 00488 int y_hr = y; 00489 00490 int x_lr = x_hr >> image_subpixel_shift; 00491 int y_lr = y_hr >> image_subpixel_shift; 00492 00493 fg = image_filter_scale / 2; 00494 00495 int x_fract = x_hr & image_subpixel_mask; 00496 unsigned y_count = diameter; 00497 00498 y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); 00499 fg_ptr = (const value_type*)base_type::source().span(x_lr + start, 00500 y_lr + start, 00501 diameter); 00502 for(;;) 00503 { 00504 x_count = diameter; 00505 weight_y = weight_array[y_hr]; 00506 x_hr = image_subpixel_mask - x_fract; 00507 for(;;) 00508 { 00509 fg += *fg_ptr * 00510 ((weight_y * weight_array[x_hr] + 00511 image_filter_scale / 2) >> 00512 image_filter_shift); 00513 if(--x_count == 0) break; 00514 x_hr += image_subpixel_scale; 00515 fg_ptr = (const value_type*)base_type::source().next_x(); 00516 } 00517 00518 if(--y_count == 0) break; 00519 y_hr += image_subpixel_scale; 00520 fg_ptr = (const value_type*)base_type::source().next_y(); 00521 } 00522 00523 fg >>= image_filter_shift; 00524 if(fg < 0) fg = 0; 00525 if(fg > base_mask) fg = base_mask; 00526 span->v = (value_type)fg; 00527 span->a = base_mask; 00528 00529 ++span; 00530 ++base_type::interpolator(); 00531 00532 } while(--len); 00533 } 00534 }; 00535 00536 00537 00538 //=========================================span_image_resample_gray_affine 00539 template<class Source> 00540 class span_image_resample_gray_affine : 00541 public span_image_resample_affine<Source> 00542 { 00543 public: 00544 typedef Source source_type; 00545 typedef typename source_type::color_type color_type; 00546 typedef span_image_resample_affine<source_type> base_type; 00547 typedef typename base_type::interpolator_type interpolator_type; 00548 typedef typename color_type::value_type value_type; 00549 typedef typename color_type::long_type long_type; 00550 enum base_scale_e 00551 { 00552 base_shift = color_type::base_shift, 00553 base_mask = color_type::base_mask, 00554 downscale_shift = image_filter_shift 00555 }; 00556 00557 //-------------------------------------------------------------------- 00558 span_image_resample_gray_affine() {} 00559 span_image_resample_gray_affine(source_type& src, 00560 interpolator_type& inter, 00561 const image_filter_lut& filter) : 00562 base_type(src, inter, filter) 00563 {} 00564 00565 00566 //-------------------------------------------------------------------- 00567 void generate(color_type* span, int x, int y, unsigned len) 00568 { 00569 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 00570 y + base_type::filter_dy_dbl(), len); 00571 00572 long_type fg; 00573 00574 int diameter = base_type::filter().diameter(); 00575 int filter_scale = diameter << image_subpixel_shift; 00576 int radius_x = (diameter * base_type::m_rx) >> 1; 00577 int radius_y = (diameter * base_type::m_ry) >> 1; 00578 int len_x_lr = 00579 (diameter * base_type::m_rx + image_subpixel_mask) >> 00580 image_subpixel_shift; 00581 00582 const int16* weight_array = base_type::filter().weight_array(); 00583 00584 do 00585 { 00586 base_type::interpolator().coordinates(&x, &y); 00587 00588 x += base_type::filter_dx_int() - radius_x; 00589 y += base_type::filter_dy_int() - radius_y; 00590 00591 fg = image_filter_scale / 2; 00592 00593 int y_lr = y >> image_subpixel_shift; 00594 int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * 00595 base_type::m_ry_inv) >> 00596 image_subpixel_shift; 00597 int total_weight = 0; 00598 int x_lr = x >> image_subpixel_shift; 00599 int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * 00600 base_type::m_rx_inv) >> 00601 image_subpixel_shift; 00602 00603 int x_hr2 = x_hr; 00604 const value_type* fg_ptr = 00605 (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); 00606 for(;;) 00607 { 00608 int weight_y = weight_array[y_hr]; 00609 x_hr = x_hr2; 00610 for(;;) 00611 { 00612 int weight = (weight_y * weight_array[x_hr] + 00613 image_filter_scale / 2) >> 00614 downscale_shift; 00615 00616 fg += *fg_ptr * weight; 00617 total_weight += weight; 00618 x_hr += base_type::m_rx_inv; 00619 if(x_hr >= filter_scale) break; 00620 fg_ptr = (const value_type*)base_type::source().next_x(); 00621 } 00622 y_hr += base_type::m_ry_inv; 00623 if(y_hr >= filter_scale) break; 00624 fg_ptr = (const value_type*)base_type::source().next_y(); 00625 } 00626 00627 fg /= total_weight; 00628 if(fg < 0) fg = 0; 00629 if(fg > base_mask) fg = base_mask; 00630 00631 span->v = (value_type)fg; 00632 span->a = base_mask; 00633 00634 ++span; 00635 ++base_type::interpolator(); 00636 } while(--len); 00637 } 00638 }; 00639 00640 00641 00642 //================================================span_image_resample_gray 00643 template<class Source, class Interpolator> 00644 class span_image_resample_gray : 00645 public span_image_resample<Source, Interpolator> 00646 { 00647 public: 00648 typedef Source source_type; 00649 typedef typename source_type::color_type color_type; 00650 typedef Interpolator interpolator_type; 00651 typedef span_image_resample<source_type, interpolator_type> base_type; 00652 typedef typename color_type::value_type value_type; 00653 typedef typename color_type::long_type long_type; 00654 enum base_scale_e 00655 { 00656 base_shift = color_type::base_shift, 00657 base_mask = color_type::base_mask, 00658 downscale_shift = image_filter_shift 00659 }; 00660 00661 //-------------------------------------------------------------------- 00662 span_image_resample_gray() {} 00663 span_image_resample_gray(source_type& src, 00664 interpolator_type& inter, 00665 const image_filter_lut& filter) : 00666 base_type(src, inter, filter) 00667 {} 00668 00669 //-------------------------------------------------------------------- 00670 void generate(color_type* span, int x, int y, unsigned len) 00671 { 00672 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 00673 y + base_type::filter_dy_dbl(), len); 00674 long_type fg; 00675 00676 int diameter = base_type::filter().diameter(); 00677 int filter_scale = diameter << image_subpixel_shift; 00678 00679 const int16* weight_array = base_type::filter().weight_array(); 00680 do 00681 { 00682 int rx; 00683 int ry; 00684 int rx_inv = image_subpixel_scale; 00685 int ry_inv = image_subpixel_scale; 00686 base_type::interpolator().coordinates(&x, &y); 00687 base_type::interpolator().local_scale(&rx, &ry); 00688 base_type::adjust_scale(&rx, &ry); 00689 00690 rx_inv = image_subpixel_scale * image_subpixel_scale / rx; 00691 ry_inv = image_subpixel_scale * image_subpixel_scale / ry; 00692 00693 int radius_x = (diameter * rx) >> 1; 00694 int radius_y = (diameter * ry) >> 1; 00695 int len_x_lr = 00696 (diameter * rx + image_subpixel_mask) >> 00697 image_subpixel_shift; 00698 00699 x += base_type::filter_dx_int() - radius_x; 00700 y += base_type::filter_dy_int() - radius_y; 00701 00702 fg = image_filter_scale / 2; 00703 00704 int y_lr = y >> image_subpixel_shift; 00705 int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * 00706 ry_inv) >> 00707 image_subpixel_shift; 00708 int total_weight = 0; 00709 int x_lr = x >> image_subpixel_shift; 00710 int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * 00711 rx_inv) >> 00712 image_subpixel_shift; 00713 int x_hr2 = x_hr; 00714 const value_type* fg_ptr = 00715 (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); 00716 00717 for(;;) 00718 { 00719 int weight_y = weight_array[y_hr]; 00720 x_hr = x_hr2; 00721 for(;;) 00722 { 00723 int weight = (weight_y * weight_array[x_hr] + 00724 image_filter_scale / 2) >> 00725 downscale_shift; 00726 fg += *fg_ptr * weight; 00727 total_weight += weight; 00728 x_hr += rx_inv; 00729 if(x_hr >= filter_scale) break; 00730 fg_ptr = (const value_type*)base_type::source().next_x(); 00731 } 00732 y_hr += ry_inv; 00733 if(y_hr >= filter_scale) break; 00734 fg_ptr = (const value_type*)base_type::source().next_y(); 00735 } 00736 00737 fg /= total_weight; 00738 if(fg < 0) fg = 0; 00739 if(fg > base_mask) fg = base_mask; 00740 00741 span->v = (value_type)fg; 00742 span->a = base_mask; 00743 00744 ++span; 00745 ++base_type::interpolator(); 00746 } while(--len); 00747 } 00748 }; 00749 00750 00751 } 00752 00753 00754 #endif 00755 00756 00757