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_RGB_INCLUDED 00033 #define AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED 00034 00035 #include "agg_basics.h" 00036 #include "agg_color_rgba.h" 00037 #include "agg_span_image_filter.h" 00038 00039 00040 namespace agg 00041 { 00042 00043 //===============================================span_image_filter_rgb_nn 00044 template<class Source, class Interpolator> 00045 class span_image_filter_rgb_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 typename source_type::order_type order_type; 00052 typedef Interpolator interpolator_type; 00053 typedef span_image_filter<source_type, interpolator_type> base_type; 00054 typedef typename color_type::value_type value_type; 00055 typedef typename color_type::calc_type calc_type; 00056 enum base_scale_e 00057 { 00058 base_shift = color_type::base_shift, 00059 base_mask = color_type::base_mask 00060 }; 00061 00062 //-------------------------------------------------------------------- 00063 span_image_filter_rgb_nn() {} 00064 span_image_filter_rgb_nn(source_type& src, 00065 interpolator_type& inter) : 00066 base_type(src, inter, 0) 00067 {} 00068 00069 //-------------------------------------------------------------------- 00070 void generate(color_type* span, int x, int y, unsigned len) 00071 { 00072 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 00073 y + base_type::filter_dy_dbl(), len); 00074 do 00075 { 00076 base_type::interpolator().coordinates(&x, &y); 00077 const value_type* fg_ptr = (const value_type*) 00078 base_type::source().span(x >> image_subpixel_shift, 00079 y >> image_subpixel_shift, 00080 1); 00081 span->r = fg_ptr[order_type::R]; 00082 span->g = fg_ptr[order_type::G]; 00083 span->b = fg_ptr[order_type::B]; 00084 span->a = base_mask; 00085 ++span; 00086 ++base_type::interpolator(); 00087 00088 } while(--len); 00089 } 00090 }; 00091 00092 00093 00094 //==========================================span_image_filter_rgb_bilinear 00095 template<class Source, class Interpolator> 00096 class span_image_filter_rgb_bilinear : 00097 public span_image_filter<Source, Interpolator> 00098 { 00099 public: 00100 typedef Source source_type; 00101 typedef typename source_type::color_type color_type; 00102 typedef typename source_type::order_type order_type; 00103 typedef Interpolator interpolator_type; 00104 typedef span_image_filter<source_type, interpolator_type> base_type; 00105 typedef typename color_type::value_type value_type; 00106 typedef typename color_type::calc_type calc_type; 00107 enum base_scale_e 00108 { 00109 base_shift = color_type::base_shift, 00110 base_mask = color_type::base_mask 00111 }; 00112 00113 //-------------------------------------------------------------------- 00114 span_image_filter_rgb_bilinear() {} 00115 span_image_filter_rgb_bilinear(source_type& src, 00116 interpolator_type& inter) : 00117 base_type(src, inter, 0) 00118 {} 00119 00120 00121 //-------------------------------------------------------------------- 00122 void generate(color_type* span, int x, int y, unsigned len) 00123 { 00124 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 00125 y + base_type::filter_dy_dbl(), len); 00126 calc_type fg[3]; 00127 const value_type *fg_ptr; 00128 do 00129 { 00130 int x_hr; 00131 int y_hr; 00132 00133 base_type::interpolator().coordinates(&x_hr, &y_hr); 00134 00135 x_hr -= base_type::filter_dx_int(); 00136 y_hr -= base_type::filter_dy_int(); 00137 00138 int x_lr = x_hr >> image_subpixel_shift; 00139 int y_lr = y_hr >> image_subpixel_shift; 00140 00141 unsigned weight; 00142 00143 fg[0] = 00144 fg[1] = 00145 fg[2] = image_subpixel_scale * image_subpixel_scale / 2; 00146 00147 x_hr &= image_subpixel_mask; 00148 y_hr &= image_subpixel_mask; 00149 00150 fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); 00151 weight = (image_subpixel_scale - x_hr) * 00152 (image_subpixel_scale - y_hr); 00153 fg[0] += weight * *fg_ptr++; 00154 fg[1] += weight * *fg_ptr++; 00155 fg[2] += weight * *fg_ptr; 00156 00157 fg_ptr = (const value_type*)base_type::source().next_x(); 00158 weight = x_hr * (image_subpixel_scale - y_hr); 00159 fg[0] += weight * *fg_ptr++; 00160 fg[1] += weight * *fg_ptr++; 00161 fg[2] += weight * *fg_ptr; 00162 00163 fg_ptr = (const value_type*)base_type::source().next_y(); 00164 weight = (image_subpixel_scale - x_hr) * y_hr; 00165 fg[0] += weight * *fg_ptr++; 00166 fg[1] += weight * *fg_ptr++; 00167 fg[2] += weight * *fg_ptr; 00168 00169 fg_ptr = (const value_type*)base_type::source().next_x(); 00170 weight = x_hr * y_hr; 00171 fg[0] += weight * *fg_ptr++; 00172 fg[1] += weight * *fg_ptr++; 00173 fg[2] += weight * *fg_ptr; 00174 00175 span->r = value_type(fg[order_type::R] >> (image_subpixel_shift * 2)); 00176 span->g = value_type(fg[order_type::G] >> (image_subpixel_shift * 2)); 00177 span->b = value_type(fg[order_type::B] >> (image_subpixel_shift * 2)); 00178 span->a = base_mask; 00179 00180 ++span; 00181 ++base_type::interpolator(); 00182 00183 } while(--len); 00184 } 00185 }; 00186 00187 00188 00189 //=====================================span_image_filter_rgb_bilinear_clip 00190 template<class Source, class Interpolator> 00191 class span_image_filter_rgb_bilinear_clip : 00192 public span_image_filter<Source, Interpolator> 00193 { 00194 public: 00195 typedef Source source_type; 00196 typedef typename source_type::color_type color_type; 00197 typedef typename source_type::order_type order_type; 00198 typedef Interpolator interpolator_type; 00199 typedef span_image_filter<source_type, interpolator_type> base_type; 00200 typedef typename color_type::value_type value_type; 00201 typedef typename color_type::calc_type calc_type; 00202 enum base_scale_e 00203 { 00204 base_shift = color_type::base_shift, 00205 base_mask = color_type::base_mask 00206 }; 00207 00208 //-------------------------------------------------------------------- 00209 span_image_filter_rgb_bilinear_clip() {} 00210 span_image_filter_rgb_bilinear_clip(source_type& src, 00211 const color_type& back_color, 00212 interpolator_type& inter) : 00213 base_type(src, inter, 0), 00214 m_back_color(back_color) 00215 {} 00216 const color_type& background_color() const { return m_back_color; } 00217 void background_color(const color_type& v) { m_back_color = v; } 00218 00219 //-------------------------------------------------------------------- 00220 void generate(color_type* span, int x, int y, unsigned len) 00221 { 00222 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 00223 y + base_type::filter_dy_dbl(), len); 00224 calc_type fg[3]; 00225 calc_type src_alpha; 00226 value_type back_r = m_back_color.r; 00227 value_type back_g = m_back_color.g; 00228 value_type back_b = m_back_color.b; 00229 value_type back_a = m_back_color.a; 00230 00231 const value_type *fg_ptr; 00232 00233 int maxx = base_type::source().width() - 1; 00234 int maxy = base_type::source().height() - 1; 00235 00236 do 00237 { 00238 int x_hr; 00239 int y_hr; 00240 00241 base_type::interpolator().coordinates(&x_hr, &y_hr); 00242 00243 x_hr -= base_type::filter_dx_int(); 00244 y_hr -= base_type::filter_dy_int(); 00245 00246 int x_lr = x_hr >> image_subpixel_shift; 00247 int y_lr = y_hr >> image_subpixel_shift; 00248 unsigned weight; 00249 00250 if(x_lr >= 0 && y_lr >= 0 && 00251 x_lr < maxx && y_lr < maxy) 00252 { 00253 fg[0] = 00254 fg[1] = 00255 fg[2] = image_subpixel_scale * image_subpixel_scale / 2; 00256 00257 x_hr &= image_subpixel_mask; 00258 y_hr &= image_subpixel_mask; 00259 00260 fg_ptr = (const value_type*) 00261 base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; 00262 00263 weight = (image_subpixel_scale - x_hr) * 00264 (image_subpixel_scale - y_hr); 00265 fg[0] += weight * *fg_ptr++; 00266 fg[1] += weight * *fg_ptr++; 00267 fg[2] += weight * *fg_ptr++; 00268 00269 weight = x_hr * (image_subpixel_scale - y_hr); 00270 fg[0] += weight * *fg_ptr++; 00271 fg[1] += weight * *fg_ptr++; 00272 fg[2] += weight * *fg_ptr++; 00273 00274 ++y_lr; 00275 fg_ptr = (const value_type*) 00276 base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; 00277 00278 weight = (image_subpixel_scale - x_hr) * y_hr; 00279 fg[0] += weight * *fg_ptr++; 00280 fg[1] += weight * *fg_ptr++; 00281 fg[2] += weight * *fg_ptr++; 00282 00283 weight = x_hr * y_hr; 00284 fg[0] += weight * *fg_ptr++; 00285 fg[1] += weight * *fg_ptr++; 00286 fg[2] += weight * *fg_ptr++; 00287 00288 fg[0] >>= image_subpixel_shift * 2; 00289 fg[1] >>= image_subpixel_shift * 2; 00290 fg[2] >>= image_subpixel_shift * 2; 00291 src_alpha = base_mask; 00292 } 00293 else 00294 { 00295 if(x_lr < -1 || y_lr < -1 || 00296 x_lr > maxx || y_lr > maxy) 00297 { 00298 fg[order_type::R] = back_r; 00299 fg[order_type::G] = back_g; 00300 fg[order_type::B] = back_b; 00301 src_alpha = back_a; 00302 } 00303 else 00304 { 00305 fg[0] = 00306 fg[1] = 00307 fg[2] = 00308 src_alpha = image_subpixel_scale * image_subpixel_scale / 2; 00309 00310 x_hr &= image_subpixel_mask; 00311 y_hr &= image_subpixel_mask; 00312 00313 weight = (image_subpixel_scale - x_hr) * 00314 (image_subpixel_scale - y_hr); 00315 if(x_lr >= 0 && y_lr >= 0 && 00316 x_lr <= maxx && y_lr <= maxy) 00317 { 00318 fg_ptr = (const value_type*) 00319 base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; 00320 00321 fg[0] += weight * *fg_ptr++; 00322 fg[1] += weight * *fg_ptr++; 00323 fg[2] += weight * *fg_ptr++; 00324 src_alpha += weight * base_mask; 00325 } 00326 else 00327 { 00328 fg[order_type::R] += back_r * weight; 00329 fg[order_type::G] += back_g * weight; 00330 fg[order_type::B] += back_b * weight; 00331 src_alpha += back_a * weight; 00332 } 00333 00334 x_lr++; 00335 00336 weight = x_hr * (image_subpixel_scale - y_hr); 00337 if(x_lr >= 0 && y_lr >= 0 && 00338 x_lr <= maxx && y_lr <= maxy) 00339 { 00340 fg_ptr = (const value_type*) 00341 base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; 00342 00343 fg[0] += weight * *fg_ptr++; 00344 fg[1] += weight * *fg_ptr++; 00345 fg[2] += weight * *fg_ptr++; 00346 src_alpha += weight * base_mask; 00347 } 00348 else 00349 { 00350 fg[order_type::R] += back_r * weight; 00351 fg[order_type::G] += back_g * weight; 00352 fg[order_type::B] += back_b * weight; 00353 src_alpha += back_a * weight; 00354 } 00355 00356 x_lr--; 00357 y_lr++; 00358 00359 weight = (image_subpixel_scale - x_hr) * y_hr; 00360 if(x_lr >= 0 && y_lr >= 0 && 00361 x_lr <= maxx && y_lr <= maxy) 00362 { 00363 fg_ptr = (const value_type*) 00364 base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; 00365 00366 fg[0] += weight * *fg_ptr++; 00367 fg[1] += weight * *fg_ptr++; 00368 fg[2] += weight * *fg_ptr++; 00369 src_alpha += weight * base_mask; 00370 } 00371 else 00372 { 00373 fg[order_type::R] += back_r * weight; 00374 fg[order_type::G] += back_g * weight; 00375 fg[order_type::B] += back_b * weight; 00376 src_alpha += back_a * weight; 00377 } 00378 00379 x_lr++; 00380 00381 weight = x_hr * y_hr; 00382 if(x_lr >= 0 && y_lr >= 0 && 00383 x_lr <= maxx && y_lr <= maxy) 00384 { 00385 fg_ptr = (const value_type*) 00386 base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; 00387 00388 fg[0] += weight * *fg_ptr++; 00389 fg[1] += weight * *fg_ptr++; 00390 fg[2] += weight * *fg_ptr++; 00391 src_alpha += weight * base_mask; 00392 } 00393 else 00394 { 00395 fg[order_type::R] += back_r * weight; 00396 fg[order_type::G] += back_g * weight; 00397 fg[order_type::B] += back_b * weight; 00398 src_alpha += back_a * weight; 00399 } 00400 00401 fg[0] >>= image_subpixel_shift * 2; 00402 fg[1] >>= image_subpixel_shift * 2; 00403 fg[2] >>= image_subpixel_shift * 2; 00404 src_alpha >>= image_subpixel_shift * 2; 00405 } 00406 } 00407 00408 span->r = (value_type)fg[order_type::R]; 00409 span->g = (value_type)fg[order_type::G]; 00410 span->b = (value_type)fg[order_type::B]; 00411 span->a = (value_type)src_alpha; 00412 ++span; 00413 ++base_type::interpolator(); 00414 00415 } while(--len); 00416 } 00417 private: 00418 color_type m_back_color; 00419 }; 00420 00421 00422 00423 //===============================================span_image_filter_rgb_2x2 00424 template<class Source, class Interpolator> 00425 class span_image_filter_rgb_2x2 : 00426 public span_image_filter<Source, Interpolator> 00427 { 00428 public: 00429 typedef Source source_type; 00430 typedef typename source_type::color_type color_type; 00431 typedef typename source_type::order_type order_type; 00432 typedef Interpolator interpolator_type; 00433 typedef span_image_filter<source_type, interpolator_type> base_type; 00434 typedef typename color_type::value_type value_type; 00435 typedef typename color_type::calc_type calc_type; 00436 enum base_scale_e 00437 { 00438 base_shift = color_type::base_shift, 00439 base_mask = color_type::base_mask 00440 }; 00441 00442 //-------------------------------------------------------------------- 00443 span_image_filter_rgb_2x2() {} 00444 span_image_filter_rgb_2x2(source_type& src, 00445 interpolator_type& inter, 00446 const image_filter_lut& filter) : 00447 base_type(src, inter, &filter) 00448 {} 00449 00450 00451 //-------------------------------------------------------------------- 00452 void generate(color_type* span, int x, int y, unsigned len) 00453 { 00454 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 00455 y + base_type::filter_dy_dbl(), len); 00456 00457 calc_type fg[3]; 00458 00459 const value_type *fg_ptr; 00460 const int16* weight_array = base_type::filter().weight_array() + 00461 ((base_type::filter().diameter()/2 - 1) << 00462 image_subpixel_shift); 00463 do 00464 { 00465 int x_hr; 00466 int y_hr; 00467 00468 base_type::interpolator().coordinates(&x_hr, &y_hr); 00469 00470 x_hr -= base_type::filter_dx_int(); 00471 y_hr -= base_type::filter_dy_int(); 00472 00473 int x_lr = x_hr >> image_subpixel_shift; 00474 int y_lr = y_hr >> image_subpixel_shift; 00475 00476 unsigned weight; 00477 fg[0] = fg[1] = fg[2] = image_filter_scale / 2; 00478 00479 x_hr &= image_subpixel_mask; 00480 y_hr &= image_subpixel_mask; 00481 00482 fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); 00483 weight = (weight_array[x_hr + image_subpixel_scale] * 00484 weight_array[y_hr + image_subpixel_scale] + 00485 image_filter_scale / 2) >> 00486 image_filter_shift; 00487 fg[0] += weight * *fg_ptr++; 00488 fg[1] += weight * *fg_ptr++; 00489 fg[2] += weight * *fg_ptr; 00490 00491 fg_ptr = (const value_type*)base_type::source().next_x(); 00492 weight = (weight_array[x_hr] * 00493 weight_array[y_hr + image_subpixel_scale] + 00494 image_filter_scale / 2) >> 00495 image_filter_shift; 00496 fg[0] += weight * *fg_ptr++; 00497 fg[1] += weight * *fg_ptr++; 00498 fg[2] += weight * *fg_ptr; 00499 00500 fg_ptr = (const value_type*)base_type::source().next_y(); 00501 weight = (weight_array[x_hr + image_subpixel_scale] * 00502 weight_array[y_hr] + 00503 image_filter_scale / 2) >> 00504 image_filter_shift; 00505 fg[0] += weight * *fg_ptr++; 00506 fg[1] += weight * *fg_ptr++; 00507 fg[2] += weight * *fg_ptr; 00508 00509 fg_ptr = (const value_type*)base_type::source().next_x(); 00510 weight = (weight_array[x_hr] * 00511 weight_array[y_hr] + 00512 image_filter_scale / 2) >> 00513 image_filter_shift; 00514 fg[0] += weight * *fg_ptr++; 00515 fg[1] += weight * *fg_ptr++; 00516 fg[2] += weight * *fg_ptr; 00517 00518 fg[0] >>= image_filter_shift; 00519 fg[1] >>= image_filter_shift; 00520 fg[2] >>= image_filter_shift; 00521 00522 if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; 00523 if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; 00524 if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; 00525 00526 span->r = (value_type)fg[order_type::R]; 00527 span->g = (value_type)fg[order_type::G]; 00528 span->b = (value_type)fg[order_type::B]; 00529 span->a = base_mask; 00530 00531 ++span; 00532 ++base_type::interpolator(); 00533 00534 } while(--len); 00535 } 00536 }; 00537 00538 00539 00540 //===================================================span_image_filter_rgb 00541 template<class Source, class Interpolator> 00542 class span_image_filter_rgb : 00543 public span_image_filter<Source, Interpolator> 00544 { 00545 public: 00546 typedef Source source_type; 00547 typedef typename source_type::color_type color_type; 00548 typedef typename source_type::order_type order_type; 00549 typedef Interpolator interpolator_type; 00550 typedef span_image_filter<source_type, interpolator_type> base_type; 00551 typedef typename color_type::value_type value_type; 00552 typedef typename color_type::calc_type calc_type; 00553 enum base_scale_e 00554 { 00555 base_shift = color_type::base_shift, 00556 base_mask = color_type::base_mask 00557 }; 00558 00559 //-------------------------------------------------------------------- 00560 span_image_filter_rgb() {} 00561 span_image_filter_rgb(source_type& src, 00562 interpolator_type& inter, 00563 const image_filter_lut& filter) : 00564 base_type(src, inter, &filter) 00565 {} 00566 00567 //-------------------------------------------------------------------- 00568 void generate(color_type* span, int x, int y, unsigned len) 00569 { 00570 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 00571 y + base_type::filter_dy_dbl(), len); 00572 00573 int fg[3]; 00574 const value_type *fg_ptr; 00575 00576 unsigned diameter = base_type::filter().diameter(); 00577 int start = base_type::filter().start(); 00578 const int16* weight_array = base_type::filter().weight_array(); 00579 00580 int x_count; 00581 int weight_y; 00582 00583 do 00584 { 00585 base_type::interpolator().coordinates(&x, &y); 00586 00587 x -= base_type::filter_dx_int(); 00588 y -= base_type::filter_dy_int(); 00589 00590 int x_hr = x; 00591 int y_hr = y; 00592 00593 int x_lr = x_hr >> image_subpixel_shift; 00594 int y_lr = y_hr >> image_subpixel_shift; 00595 00596 fg[0] = fg[1] = fg[2] = image_filter_scale / 2; 00597 00598 int x_fract = x_hr & image_subpixel_mask; 00599 unsigned y_count = diameter; 00600 00601 y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); 00602 fg_ptr = (const value_type*)base_type::source().span(x_lr + start, 00603 y_lr + start, 00604 diameter); 00605 for(;;) 00606 { 00607 x_count = diameter; 00608 weight_y = weight_array[y_hr]; 00609 x_hr = image_subpixel_mask - x_fract; 00610 for(;;) 00611 { 00612 int weight = (weight_y * weight_array[x_hr] + 00613 image_filter_scale / 2) >> 00614 image_filter_shift; 00615 00616 fg[0] += weight * *fg_ptr++; 00617 fg[1] += weight * *fg_ptr++; 00618 fg[2] += weight * *fg_ptr; 00619 00620 if(--x_count == 0) break; 00621 x_hr += image_subpixel_scale; 00622 fg_ptr = (const value_type*)base_type::source().next_x(); 00623 } 00624 00625 if(--y_count == 0) break; 00626 y_hr += image_subpixel_scale; 00627 fg_ptr = (const value_type*)base_type::source().next_y(); 00628 } 00629 00630 fg[0] >>= image_filter_shift; 00631 fg[1] >>= image_filter_shift; 00632 fg[2] >>= image_filter_shift; 00633 00634 if(fg[0] < 0) fg[0] = 0; 00635 if(fg[1] < 0) fg[1] = 0; 00636 if(fg[2] < 0) fg[2] = 0; 00637 00638 if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; 00639 if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; 00640 if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; 00641 00642 span->r = (value_type)fg[order_type::R]; 00643 span->g = (value_type)fg[order_type::G]; 00644 span->b = (value_type)fg[order_type::B]; 00645 span->a = base_mask; 00646 00647 ++span; 00648 ++base_type::interpolator(); 00649 00650 } while(--len); 00651 } 00652 }; 00653 00654 00655 00656 //==========================================span_image_resample_rgb_affine 00657 template<class Source> 00658 class span_image_resample_rgb_affine : 00659 public span_image_resample_affine<Source> 00660 { 00661 public: 00662 typedef Source source_type; 00663 typedef typename source_type::color_type color_type; 00664 typedef typename source_type::order_type order_type; 00665 typedef span_image_resample_affine<source_type> base_type; 00666 typedef typename base_type::interpolator_type interpolator_type; 00667 typedef typename color_type::value_type value_type; 00668 typedef typename color_type::long_type long_type; 00669 enum base_scale_e 00670 { 00671 base_shift = color_type::base_shift, 00672 base_mask = color_type::base_mask, 00673 downscale_shift = image_filter_shift 00674 }; 00675 00676 //-------------------------------------------------------------------- 00677 span_image_resample_rgb_affine() {} 00678 span_image_resample_rgb_affine(source_type& src, 00679 interpolator_type& inter, 00680 const image_filter_lut& filter) : 00681 base_type(src, inter, filter) 00682 {} 00683 00684 00685 //-------------------------------------------------------------------- 00686 void generate(color_type* span, int x, int y, unsigned len) 00687 { 00688 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 00689 y + base_type::filter_dy_dbl(), len); 00690 00691 long_type fg[3]; 00692 00693 int diameter = base_type::filter().diameter(); 00694 int filter_scale = diameter << image_subpixel_shift; 00695 int radius_x = (diameter * base_type::m_rx) >> 1; 00696 int radius_y = (diameter * base_type::m_ry) >> 1; 00697 int len_x_lr = 00698 (diameter * base_type::m_rx + image_subpixel_mask) >> 00699 image_subpixel_shift; 00700 00701 const int16* weight_array = base_type::filter().weight_array(); 00702 00703 do 00704 { 00705 base_type::interpolator().coordinates(&x, &y); 00706 00707 x += base_type::filter_dx_int() - radius_x; 00708 y += base_type::filter_dy_int() - radius_y; 00709 00710 fg[0] = fg[1] = fg[2] = image_filter_scale / 2; 00711 00712 int y_lr = y >> image_subpixel_shift; 00713 int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * 00714 base_type::m_ry_inv) >> 00715 image_subpixel_shift; 00716 int total_weight = 0; 00717 int x_lr = x >> image_subpixel_shift; 00718 int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * 00719 base_type::m_rx_inv) >> 00720 image_subpixel_shift; 00721 00722 int x_hr2 = x_hr; 00723 const value_type* fg_ptr = 00724 (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); 00725 for(;;) 00726 { 00727 int weight_y = weight_array[y_hr]; 00728 x_hr = x_hr2; 00729 for(;;) 00730 { 00731 int weight = (weight_y * weight_array[x_hr] + 00732 image_filter_scale / 2) >> 00733 downscale_shift; 00734 00735 fg[0] += *fg_ptr++ * weight; 00736 fg[1] += *fg_ptr++ * weight; 00737 fg[2] += *fg_ptr * weight; 00738 total_weight += weight; 00739 x_hr += base_type::m_rx_inv; 00740 if(x_hr >= filter_scale) break; 00741 fg_ptr = (const value_type*)base_type::source().next_x(); 00742 } 00743 y_hr += base_type::m_ry_inv; 00744 if(y_hr >= filter_scale) break; 00745 fg_ptr = (const value_type*)base_type::source().next_y(); 00746 } 00747 00748 fg[0] /= total_weight; 00749 fg[1] /= total_weight; 00750 fg[2] /= total_weight; 00751 00752 if(fg[0] < 0) fg[0] = 0; 00753 if(fg[1] < 0) fg[1] = 0; 00754 if(fg[2] < 0) fg[2] = 0; 00755 00756 if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; 00757 if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; 00758 if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; 00759 00760 span->r = (value_type)fg[order_type::R]; 00761 span->g = (value_type)fg[order_type::G]; 00762 span->b = (value_type)fg[order_type::B]; 00763 span->a = base_mask; 00764 00765 ++span; 00766 ++base_type::interpolator(); 00767 } while(--len); 00768 } 00769 }; 00770 00771 00772 00773 //=================================================span_image_resample_rgb 00774 template<class Source, class Interpolator> 00775 class span_image_resample_rgb : 00776 public span_image_resample<Source, Interpolator> 00777 { 00778 public: 00779 typedef Source source_type; 00780 typedef typename source_type::color_type color_type; 00781 typedef typename source_type::order_type order_type; 00782 typedef Interpolator interpolator_type; 00783 typedef span_image_resample<source_type, interpolator_type> base_type; 00784 typedef typename color_type::value_type value_type; 00785 typedef typename color_type::long_type long_type; 00786 enum base_scale_e 00787 { 00788 base_shift = color_type::base_shift, 00789 base_mask = color_type::base_mask, 00790 downscale_shift = image_filter_shift 00791 }; 00792 00793 //-------------------------------------------------------------------- 00794 span_image_resample_rgb() {} 00795 span_image_resample_rgb(source_type& src, 00796 interpolator_type& inter, 00797 const image_filter_lut& filter) : 00798 base_type(src, inter, filter) 00799 {} 00800 00801 //-------------------------------------------------------------------- 00802 void generate(color_type* span, int x, int y, unsigned len) 00803 { 00804 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 00805 y + base_type::filter_dy_dbl(), len); 00806 long_type fg[3]; 00807 00808 int diameter = base_type::filter().diameter(); 00809 int filter_scale = diameter << image_subpixel_shift; 00810 00811 const int16* weight_array = base_type::filter().weight_array(); 00812 do 00813 { 00814 int rx; 00815 int ry; 00816 int rx_inv = image_subpixel_scale; 00817 int ry_inv = image_subpixel_scale; 00818 base_type::interpolator().coordinates(&x, &y); 00819 base_type::interpolator().local_scale(&rx, &ry); 00820 base_type::adjust_scale(&rx, &ry); 00821 00822 rx_inv = image_subpixel_scale * image_subpixel_scale / rx; 00823 ry_inv = image_subpixel_scale * image_subpixel_scale / ry; 00824 00825 int radius_x = (diameter * rx) >> 1; 00826 int radius_y = (diameter * ry) >> 1; 00827 int len_x_lr = 00828 (diameter * rx + image_subpixel_mask) >> 00829 image_subpixel_shift; 00830 00831 x += base_type::filter_dx_int() - radius_x; 00832 y += base_type::filter_dy_int() - radius_y; 00833 00834 fg[0] = fg[1] = fg[2] = image_filter_scale / 2; 00835 00836 int y_lr = y >> image_subpixel_shift; 00837 int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * 00838 ry_inv) >> 00839 image_subpixel_shift; 00840 int total_weight = 0; 00841 int x_lr = x >> image_subpixel_shift; 00842 int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * 00843 rx_inv) >> 00844 image_subpixel_shift; 00845 int x_hr2 = x_hr; 00846 const value_type* fg_ptr = 00847 (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); 00848 00849 for(;;) 00850 { 00851 int weight_y = weight_array[y_hr]; 00852 x_hr = x_hr2; 00853 for(;;) 00854 { 00855 int weight = (weight_y * weight_array[x_hr] + 00856 image_filter_scale / 2) >> 00857 downscale_shift; 00858 fg[0] += *fg_ptr++ * weight; 00859 fg[1] += *fg_ptr++ * weight; 00860 fg[2] += *fg_ptr * weight; 00861 total_weight += weight; 00862 x_hr += rx_inv; 00863 if(x_hr >= filter_scale) break; 00864 fg_ptr = (const value_type*)base_type::source().next_x(); 00865 } 00866 y_hr += ry_inv; 00867 if(y_hr >= filter_scale) break; 00868 fg_ptr = (const value_type*)base_type::source().next_y(); 00869 } 00870 00871 fg[0] /= total_weight; 00872 fg[1] /= total_weight; 00873 fg[2] /= total_weight; 00874 00875 if(fg[0] < 0) fg[0] = 0; 00876 if(fg[1] < 0) fg[1] = 0; 00877 if(fg[2] < 0) fg[2] = 0; 00878 00879 if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; 00880 if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; 00881 if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; 00882 00883 span->r = (value_type)fg[order_type::R]; 00884 span->g = (value_type)fg[order_type::G]; 00885 span->b = (value_type)fg[order_type::B]; 00886 span->a = base_mask; 00887 00888 ++span; 00889 ++base_type::interpolator(); 00890 } while(--len); 00891 } 00892 }; 00893 00894 00895 } 00896 00897 00898 #endif 00899 00900 00901