1//---------------------------------------------------------------------------- 2// Anti-Grain Geometry - Version 2.4 3// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) 4// 5// Permission to copy, use, modify, sell and distribute this software 6// is granted provided this copyright notice appears in all copies. 7// This software is provided "as is" without express or implied 8// warranty, and with no claim as to its suitability for any purpose. 9// 10//---------------------------------------------------------------------------- 11// Contact: mcseem@antigrain.com 12// mcseemagg@yahoo.com 13// http://www.antigrain.com 14//---------------------------------------------------------------------------- 15// 16// Adaptation for high precision colors has been sponsored by 17// Liberty Technology Systems, Inc., visit http://lib-sys.com 18// 19// Liberty Technology Systems, Inc. is the provider of 20// PostScript and PDF technology for software developers. 21// 22//---------------------------------------------------------------------------- 23#ifndef AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED 24#define AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED 25 26#include "agg_basics.h" 27#include "agg_color_rgba.h" 28#include "agg_span_image_filter.h" 29 30 31namespace agg 32{ 33 34 //===============================================span_image_filter_rgb_nn 35 template<class Source, class Interpolator> 36 class span_image_filter_rgb_nn : 37 public span_image_filter<Source, Interpolator> 38 { 39 public: 40 typedef Source source_type; 41 typedef typename source_type::color_type color_type; 42 typedef typename source_type::order_type order_type; 43 typedef Interpolator interpolator_type; 44 typedef span_image_filter<source_type, interpolator_type> base_type; 45 typedef typename color_type::value_type value_type; 46 typedef typename color_type::calc_type calc_type; 47 enum base_scale_e 48 { 49 base_shift = color_type::base_shift, 50 base_mask = color_type::base_mask 51 }; 52 53 //-------------------------------------------------------------------- 54 span_image_filter_rgb_nn() {} 55 span_image_filter_rgb_nn(source_type& src, 56 interpolator_type& inter) : 57 base_type(src, inter, 0) 58 {} 59 60 //-------------------------------------------------------------------- 61 void generate(color_type* span, int x, int y, unsigned len) 62 { 63 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 64 y + base_type::filter_dy_dbl(), len); 65 do 66 { 67 base_type::interpolator().coordinates(&x, &y); 68 const value_type* fg_ptr = (const value_type*) 69 base_type::source().span(x >> image_subpixel_shift, 70 y >> image_subpixel_shift, 71 1); 72 span->r = fg_ptr[order_type::R]; 73 span->g = fg_ptr[order_type::G]; 74 span->b = fg_ptr[order_type::B]; 75 span->a = base_mask; 76 ++span; 77 ++base_type::interpolator(); 78 79 } while(--len); 80 } 81 }; 82 83 84 85 //==========================================span_image_filter_rgb_bilinear 86 template<class Source, class Interpolator> 87 class span_image_filter_rgb_bilinear : 88 public span_image_filter<Source, Interpolator> 89 { 90 public: 91 typedef Source source_type; 92 typedef typename source_type::color_type color_type; 93 typedef typename source_type::order_type order_type; 94 typedef Interpolator interpolator_type; 95 typedef span_image_filter<source_type, interpolator_type> base_type; 96 typedef typename color_type::value_type value_type; 97 typedef typename color_type::calc_type calc_type; 98 enum base_scale_e 99 { 100 base_shift = color_type::base_shift, 101 base_mask = color_type::base_mask 102 }; 103 104 //-------------------------------------------------------------------- 105 span_image_filter_rgb_bilinear() {} 106 span_image_filter_rgb_bilinear(source_type& src, 107 interpolator_type& inter) : 108 base_type(src, inter, 0) 109 {} 110 111 112 //-------------------------------------------------------------------- 113 void generate(color_type* span, int x, int y, unsigned len) 114 { 115 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 116 y + base_type::filter_dy_dbl(), len); 117 calc_type fg[3]; 118 const value_type *fg_ptr; 119 do 120 { 121 int x_hr; 122 int y_hr; 123 124 base_type::interpolator().coordinates(&x_hr, &y_hr); 125 126 x_hr -= base_type::filter_dx_int(); 127 y_hr -= base_type::filter_dy_int(); 128 129 int x_lr = x_hr >> image_subpixel_shift; 130 int y_lr = y_hr >> image_subpixel_shift; 131 132 unsigned weight; 133 134 fg[0] = 135 fg[1] = 136 fg[2] = image_subpixel_scale * image_subpixel_scale / 2; 137 138 x_hr &= image_subpixel_mask; 139 y_hr &= image_subpixel_mask; 140 141 fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); 142 weight = (image_subpixel_scale - x_hr) * 143 (image_subpixel_scale - y_hr); 144 fg[0] += weight * *fg_ptr++; 145 fg[1] += weight * *fg_ptr++; 146 fg[2] += weight * *fg_ptr; 147 148 fg_ptr = (const value_type*)base_type::source().next_x(); 149 weight = x_hr * (image_subpixel_scale - y_hr); 150 fg[0] += weight * *fg_ptr++; 151 fg[1] += weight * *fg_ptr++; 152 fg[2] += weight * *fg_ptr; 153 154 fg_ptr = (const value_type*)base_type::source().next_y(); 155 weight = (image_subpixel_scale - x_hr) * y_hr; 156 fg[0] += weight * *fg_ptr++; 157 fg[1] += weight * *fg_ptr++; 158 fg[2] += weight * *fg_ptr; 159 160 fg_ptr = (const value_type*)base_type::source().next_x(); 161 weight = x_hr * y_hr; 162 fg[0] += weight * *fg_ptr++; 163 fg[1] += weight * *fg_ptr++; 164 fg[2] += weight * *fg_ptr; 165 166 span->r = value_type(fg[order_type::R] >> (image_subpixel_shift * 2)); 167 span->g = value_type(fg[order_type::G] >> (image_subpixel_shift * 2)); 168 span->b = value_type(fg[order_type::B] >> (image_subpixel_shift * 2)); 169 span->a = base_mask; 170 171 ++span; 172 ++base_type::interpolator(); 173 174 } while(--len); 175 } 176 }; 177 178 179 180 //=====================================span_image_filter_rgb_bilinear_clip 181 template<class Source, class Interpolator> 182 class span_image_filter_rgb_bilinear_clip : 183 public span_image_filter<Source, Interpolator> 184 { 185 public: 186 typedef Source source_type; 187 typedef typename source_type::color_type color_type; 188 typedef typename source_type::order_type order_type; 189 typedef Interpolator interpolator_type; 190 typedef span_image_filter<source_type, interpolator_type> base_type; 191 typedef typename color_type::value_type value_type; 192 typedef typename color_type::calc_type calc_type; 193 enum base_scale_e 194 { 195 base_shift = color_type::base_shift, 196 base_mask = color_type::base_mask 197 }; 198 199 //-------------------------------------------------------------------- 200 span_image_filter_rgb_bilinear_clip() {} 201 span_image_filter_rgb_bilinear_clip(source_type& src, 202 const color_type& back_color, 203 interpolator_type& inter) : 204 base_type(src, inter, 0), 205 m_back_color(back_color) 206 {} 207 const color_type& background_color() const { return m_back_color; } 208 void background_color(const color_type& v) { m_back_color = v; } 209 210 //-------------------------------------------------------------------- 211 void generate(color_type* span, int x, int y, unsigned len) 212 { 213 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 214 y + base_type::filter_dy_dbl(), len); 215 calc_type fg[3]; 216 calc_type src_alpha; 217 value_type back_r = m_back_color.r; 218 value_type back_g = m_back_color.g; 219 value_type back_b = m_back_color.b; 220 value_type back_a = m_back_color.a; 221 222 const value_type *fg_ptr; 223 224 int maxx = base_type::source().width() - 1; 225 int maxy = base_type::source().height() - 1; 226 227 do 228 { 229 int x_hr; 230 int y_hr; 231 232 base_type::interpolator().coordinates(&x_hr, &y_hr); 233 234 x_hr -= base_type::filter_dx_int(); 235 y_hr -= base_type::filter_dy_int(); 236 237 int x_lr = x_hr >> image_subpixel_shift; 238 int y_lr = y_hr >> image_subpixel_shift; 239 unsigned weight; 240 241 if(x_lr >= 0 && y_lr >= 0 && 242 x_lr < maxx && y_lr < maxy) 243 { 244 fg[0] = 245 fg[1] = 246 fg[2] = image_subpixel_scale * image_subpixel_scale / 2; 247 248 x_hr &= image_subpixel_mask; 249 y_hr &= image_subpixel_mask; 250 251 fg_ptr = (const value_type*) 252 base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; 253 254 weight = (image_subpixel_scale - x_hr) * 255 (image_subpixel_scale - y_hr); 256 fg[0] += weight * *fg_ptr++; 257 fg[1] += weight * *fg_ptr++; 258 fg[2] += weight * *fg_ptr++; 259 260 weight = x_hr * (image_subpixel_scale - y_hr); 261 fg[0] += weight * *fg_ptr++; 262 fg[1] += weight * *fg_ptr++; 263 fg[2] += weight * *fg_ptr++; 264 265 ++y_lr; 266 fg_ptr = (const value_type*) 267 base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; 268 269 weight = (image_subpixel_scale - x_hr) * y_hr; 270 fg[0] += weight * *fg_ptr++; 271 fg[1] += weight * *fg_ptr++; 272 fg[2] += weight * *fg_ptr++; 273 274 weight = x_hr * y_hr; 275 fg[0] += weight * *fg_ptr++; 276 fg[1] += weight * *fg_ptr++; 277 fg[2] += weight * *fg_ptr++; 278 279 fg[0] >>= image_subpixel_shift * 2; 280 fg[1] >>= image_subpixel_shift * 2; 281 fg[2] >>= image_subpixel_shift * 2; 282 src_alpha = base_mask; 283 } 284 else 285 { 286 if(x_lr < -1 || y_lr < -1 || 287 x_lr > maxx || y_lr > maxy) 288 { 289 fg[order_type::R] = back_r; 290 fg[order_type::G] = back_g; 291 fg[order_type::B] = back_b; 292 src_alpha = back_a; 293 } 294 else 295 { 296 fg[0] = 297 fg[1] = 298 fg[2] = 299 src_alpha = image_subpixel_scale * image_subpixel_scale / 2; 300 301 x_hr &= image_subpixel_mask; 302 y_hr &= image_subpixel_mask; 303 304 weight = (image_subpixel_scale - x_hr) * 305 (image_subpixel_scale - y_hr); 306 if(x_lr >= 0 && y_lr >= 0 && 307 x_lr <= maxx && y_lr <= maxy) 308 { 309 fg_ptr = (const value_type*) 310 base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; 311 312 fg[0] += weight * *fg_ptr++; 313 fg[1] += weight * *fg_ptr++; 314 fg[2] += weight * *fg_ptr++; 315 src_alpha += weight * base_mask; 316 } 317 else 318 { 319 fg[order_type::R] += back_r * weight; 320 fg[order_type::G] += back_g * weight; 321 fg[order_type::B] += back_b * weight; 322 src_alpha += back_a * weight; 323 } 324 325 x_lr++; 326 327 weight = x_hr * (image_subpixel_scale - y_hr); 328 if(x_lr >= 0 && y_lr >= 0 && 329 x_lr <= maxx && y_lr <= maxy) 330 { 331 fg_ptr = (const value_type*) 332 base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; 333 334 fg[0] += weight * *fg_ptr++; 335 fg[1] += weight * *fg_ptr++; 336 fg[2] += weight * *fg_ptr++; 337 src_alpha += weight * base_mask; 338 } 339 else 340 { 341 fg[order_type::R] += back_r * weight; 342 fg[order_type::G] += back_g * weight; 343 fg[order_type::B] += back_b * weight; 344 src_alpha += back_a * weight; 345 } 346 347 x_lr--; 348 y_lr++; 349 350 weight = (image_subpixel_scale - x_hr) * y_hr; 351 if(x_lr >= 0 && y_lr >= 0 && 352 x_lr <= maxx && y_lr <= maxy) 353 { 354 fg_ptr = (const value_type*) 355 base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; 356 357 fg[0] += weight * *fg_ptr++; 358 fg[1] += weight * *fg_ptr++; 359 fg[2] += weight * *fg_ptr++; 360 src_alpha += weight * base_mask; 361 } 362 else 363 { 364 fg[order_type::R] += back_r * weight; 365 fg[order_type::G] += back_g * weight; 366 fg[order_type::B] += back_b * weight; 367 src_alpha += back_a * weight; 368 } 369 370 x_lr++; 371 372 weight = x_hr * y_hr; 373 if(x_lr >= 0 && y_lr >= 0 && 374 x_lr <= maxx && y_lr <= maxy) 375 { 376 fg_ptr = (const value_type*) 377 base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; 378 379 fg[0] += weight * *fg_ptr++; 380 fg[1] += weight * *fg_ptr++; 381 fg[2] += weight * *fg_ptr++; 382 src_alpha += weight * base_mask; 383 } 384 else 385 { 386 fg[order_type::R] += back_r * weight; 387 fg[order_type::G] += back_g * weight; 388 fg[order_type::B] += back_b * weight; 389 src_alpha += back_a * weight; 390 } 391 392 fg[0] >>= image_subpixel_shift * 2; 393 fg[1] >>= image_subpixel_shift * 2; 394 fg[2] >>= image_subpixel_shift * 2; 395 src_alpha >>= image_subpixel_shift * 2; 396 } 397 } 398 399 span->r = (value_type)fg[order_type::R]; 400 span->g = (value_type)fg[order_type::G]; 401 span->b = (value_type)fg[order_type::B]; 402 span->a = (value_type)src_alpha; 403 ++span; 404 ++base_type::interpolator(); 405 406 } while(--len); 407 } 408 private: 409 color_type m_back_color; 410 }; 411 412 413 414 //===============================================span_image_filter_rgb_2x2 415 template<class Source, class Interpolator> 416 class span_image_filter_rgb_2x2 : 417 public span_image_filter<Source, Interpolator> 418 { 419 public: 420 typedef Source source_type; 421 typedef typename source_type::color_type color_type; 422 typedef typename source_type::order_type order_type; 423 typedef Interpolator interpolator_type; 424 typedef span_image_filter<source_type, interpolator_type> base_type; 425 typedef typename color_type::value_type value_type; 426 typedef typename color_type::calc_type calc_type; 427 enum base_scale_e 428 { 429 base_shift = color_type::base_shift, 430 base_mask = color_type::base_mask 431 }; 432 433 //-------------------------------------------------------------------- 434 span_image_filter_rgb_2x2() {} 435 span_image_filter_rgb_2x2(source_type& src, 436 interpolator_type& inter, 437 const image_filter_lut& filter) : 438 base_type(src, inter, &filter) 439 {} 440 441 442 //-------------------------------------------------------------------- 443 void generate(color_type* span, int x, int y, unsigned len) 444 { 445 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 446 y + base_type::filter_dy_dbl(), len); 447 448 calc_type fg[3]; 449 450 const value_type *fg_ptr; 451 const int16* weight_array = base_type::filter().weight_array() + 452 ((base_type::filter().diameter()/2 - 1) << 453 image_subpixel_shift); 454 do 455 { 456 int x_hr; 457 int y_hr; 458 459 base_type::interpolator().coordinates(&x_hr, &y_hr); 460 461 x_hr -= base_type::filter_dx_int(); 462 y_hr -= base_type::filter_dy_int(); 463 464 int x_lr = x_hr >> image_subpixel_shift; 465 int y_lr = y_hr >> image_subpixel_shift; 466 467 unsigned weight; 468 fg[0] = fg[1] = fg[2] = image_filter_scale / 2; 469 470 x_hr &= image_subpixel_mask; 471 y_hr &= image_subpixel_mask; 472 473 fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); 474 weight = (weight_array[x_hr + image_subpixel_scale] * 475 weight_array[y_hr + image_subpixel_scale] + 476 image_filter_scale / 2) >> 477 image_filter_shift; 478 fg[0] += weight * *fg_ptr++; 479 fg[1] += weight * *fg_ptr++; 480 fg[2] += weight * *fg_ptr; 481 482 fg_ptr = (const value_type*)base_type::source().next_x(); 483 weight = (weight_array[x_hr] * 484 weight_array[y_hr + image_subpixel_scale] + 485 image_filter_scale / 2) >> 486 image_filter_shift; 487 fg[0] += weight * *fg_ptr++; 488 fg[1] += weight * *fg_ptr++; 489 fg[2] += weight * *fg_ptr; 490 491 fg_ptr = (const value_type*)base_type::source().next_y(); 492 weight = (weight_array[x_hr + image_subpixel_scale] * 493 weight_array[y_hr] + 494 image_filter_scale / 2) >> 495 image_filter_shift; 496 fg[0] += weight * *fg_ptr++; 497 fg[1] += weight * *fg_ptr++; 498 fg[2] += weight * *fg_ptr; 499 500 fg_ptr = (const value_type*)base_type::source().next_x(); 501 weight = (weight_array[x_hr] * 502 weight_array[y_hr] + 503 image_filter_scale / 2) >> 504 image_filter_shift; 505 fg[0] += weight * *fg_ptr++; 506 fg[1] += weight * *fg_ptr++; 507 fg[2] += weight * *fg_ptr; 508 509 fg[0] >>= image_filter_shift; 510 fg[1] >>= image_filter_shift; 511 fg[2] >>= image_filter_shift; 512 513 if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; 514 if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; 515 if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; 516 517 span->r = (value_type)fg[order_type::R]; 518 span->g = (value_type)fg[order_type::G]; 519 span->b = (value_type)fg[order_type::B]; 520 span->a = base_mask; 521 522 ++span; 523 ++base_type::interpolator(); 524 525 } while(--len); 526 } 527 }; 528 529 530 531 //===================================================span_image_filter_rgb 532 template<class Source, class Interpolator> 533 class span_image_filter_rgb : 534 public span_image_filter<Source, Interpolator> 535 { 536 public: 537 typedef Source source_type; 538 typedef typename source_type::color_type color_type; 539 typedef typename source_type::order_type order_type; 540 typedef Interpolator interpolator_type; 541 typedef span_image_filter<source_type, interpolator_type> base_type; 542 typedef typename color_type::value_type value_type; 543 typedef typename color_type::calc_type calc_type; 544 enum base_scale_e 545 { 546 base_shift = color_type::base_shift, 547 base_mask = color_type::base_mask 548 }; 549 550 //-------------------------------------------------------------------- 551 span_image_filter_rgb() {} 552 span_image_filter_rgb(source_type& src, 553 interpolator_type& inter, 554 const image_filter_lut& filter) : 555 base_type(src, inter, &filter) 556 {} 557 558 //-------------------------------------------------------------------- 559 void generate(color_type* span, int x, int y, unsigned len) 560 { 561 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 562 y + base_type::filter_dy_dbl(), len); 563 564 int fg[3]; 565 const value_type *fg_ptr; 566 567 unsigned diameter = base_type::filter().diameter(); 568 int start = base_type::filter().start(); 569 const int16* weight_array = base_type::filter().weight_array(); 570 571 int x_count; 572 int weight_y; 573 574 do 575 { 576 base_type::interpolator().coordinates(&x, &y); 577 578 x -= base_type::filter_dx_int(); 579 y -= base_type::filter_dy_int(); 580 581 int x_hr = x; 582 int y_hr = y; 583 584 int x_lr = x_hr >> image_subpixel_shift; 585 int y_lr = y_hr >> image_subpixel_shift; 586 587 fg[0] = fg[1] = fg[2] = image_filter_scale / 2; 588 589 int x_fract = x_hr & image_subpixel_mask; 590 unsigned y_count = diameter; 591 592 y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); 593 fg_ptr = (const value_type*)base_type::source().span(x_lr + start, 594 y_lr + start, 595 diameter); 596 for(;;) 597 { 598 x_count = diameter; 599 weight_y = weight_array[y_hr]; 600 x_hr = image_subpixel_mask - x_fract; 601 for(;;) 602 { 603 int weight = (weight_y * weight_array[x_hr] + 604 image_filter_scale / 2) >> 605 image_filter_shift; 606 607 fg[0] += weight * *fg_ptr++; 608 fg[1] += weight * *fg_ptr++; 609 fg[2] += weight * *fg_ptr; 610 611 if(--x_count == 0) break; 612 x_hr += image_subpixel_scale; 613 fg_ptr = (const value_type*)base_type::source().next_x(); 614 } 615 616 if(--y_count == 0) break; 617 y_hr += image_subpixel_scale; 618 fg_ptr = (const value_type*)base_type::source().next_y(); 619 } 620 621 fg[0] >>= image_filter_shift; 622 fg[1] >>= image_filter_shift; 623 fg[2] >>= image_filter_shift; 624 625 if(fg[0] < 0) fg[0] = 0; 626 if(fg[1] < 0) fg[1] = 0; 627 if(fg[2] < 0) fg[2] = 0; 628 629 if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; 630 if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; 631 if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; 632 633 span->r = (value_type)fg[order_type::R]; 634 span->g = (value_type)fg[order_type::G]; 635 span->b = (value_type)fg[order_type::B]; 636 span->a = base_mask; 637 638 ++span; 639 ++base_type::interpolator(); 640 641 } while(--len); 642 } 643 }; 644 645 646 647 //==========================================span_image_resample_rgb_affine 648 template<class Source> 649 class span_image_resample_rgb_affine : 650 public span_image_resample_affine<Source> 651 { 652 public: 653 typedef Source source_type; 654 typedef typename source_type::color_type color_type; 655 typedef typename source_type::order_type order_type; 656 typedef span_image_resample_affine<source_type> base_type; 657 typedef typename base_type::interpolator_type interpolator_type; 658 typedef typename color_type::value_type value_type; 659 typedef typename color_type::long_type long_type; 660 enum base_scale_e 661 { 662 base_shift = color_type::base_shift, 663 base_mask = color_type::base_mask, 664 downscale_shift = image_filter_shift 665 }; 666 667 //-------------------------------------------------------------------- 668 span_image_resample_rgb_affine() {} 669 span_image_resample_rgb_affine(source_type& src, 670 interpolator_type& inter, 671 const image_filter_lut& filter) : 672 base_type(src, inter, filter) 673 {} 674 675 676 //-------------------------------------------------------------------- 677 void generate(color_type* span, int x, int y, unsigned len) 678 { 679 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 680 y + base_type::filter_dy_dbl(), len); 681 682 long_type fg[3]; 683 684 int diameter = base_type::filter().diameter(); 685 int filter_scale = diameter << image_subpixel_shift; 686 int radius_x = (diameter * base_type::m_rx) >> 1; 687 int radius_y = (diameter * base_type::m_ry) >> 1; 688 int len_x_lr = 689 (diameter * base_type::m_rx + image_subpixel_mask) >> 690 image_subpixel_shift; 691 692 const int16* weight_array = base_type::filter().weight_array(); 693 694 do 695 { 696 base_type::interpolator().coordinates(&x, &y); 697 698 x += base_type::filter_dx_int() - radius_x; 699 y += base_type::filter_dy_int() - radius_y; 700 701 fg[0] = fg[1] = fg[2] = image_filter_scale / 2; 702 703 int y_lr = y >> image_subpixel_shift; 704 int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * 705 base_type::m_ry_inv) >> 706 image_subpixel_shift; 707 int total_weight = 0; 708 int x_lr = x >> image_subpixel_shift; 709 int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * 710 base_type::m_rx_inv) >> 711 image_subpixel_shift; 712 713 int x_hr2 = x_hr; 714 const value_type* fg_ptr = 715 (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); 716 for(;;) 717 { 718 int weight_y = weight_array[y_hr]; 719 x_hr = x_hr2; 720 for(;;) 721 { 722 int weight = (weight_y * weight_array[x_hr] + 723 image_filter_scale / 2) >> 724 downscale_shift; 725 726 fg[0] += *fg_ptr++ * weight; 727 fg[1] += *fg_ptr++ * weight; 728 fg[2] += *fg_ptr * weight; 729 total_weight += weight; 730 x_hr += base_type::m_rx_inv; 731 if(x_hr >= filter_scale) break; 732 fg_ptr = (const value_type*)base_type::source().next_x(); 733 } 734 y_hr += base_type::m_ry_inv; 735 if(y_hr >= filter_scale) break; 736 fg_ptr = (const value_type*)base_type::source().next_y(); 737 } 738 739 fg[0] /= total_weight; 740 fg[1] /= total_weight; 741 fg[2] /= total_weight; 742 743 if(fg[0] < 0) fg[0] = 0; 744 if(fg[1] < 0) fg[1] = 0; 745 if(fg[2] < 0) fg[2] = 0; 746 747 if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; 748 if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; 749 if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; 750 751 span->r = (value_type)fg[order_type::R]; 752 span->g = (value_type)fg[order_type::G]; 753 span->b = (value_type)fg[order_type::B]; 754 span->a = base_mask; 755 756 ++span; 757 ++base_type::interpolator(); 758 } while(--len); 759 } 760 }; 761 762 763 764 //=================================================span_image_resample_rgb 765 template<class Source, class Interpolator> 766 class span_image_resample_rgb : 767 public span_image_resample<Source, Interpolator> 768 { 769 public: 770 typedef Source source_type; 771 typedef typename source_type::color_type color_type; 772 typedef typename source_type::order_type order_type; 773 typedef Interpolator interpolator_type; 774 typedef span_image_resample<source_type, interpolator_type> base_type; 775 typedef typename color_type::value_type value_type; 776 typedef typename color_type::long_type long_type; 777 enum base_scale_e 778 { 779 base_shift = color_type::base_shift, 780 base_mask = color_type::base_mask, 781 downscale_shift = image_filter_shift 782 }; 783 784 //-------------------------------------------------------------------- 785 span_image_resample_rgb() {} 786 span_image_resample_rgb(source_type& src, 787 interpolator_type& inter, 788 const image_filter_lut& filter) : 789 base_type(src, inter, filter) 790 {} 791 792 //-------------------------------------------------------------------- 793 void generate(color_type* span, int x, int y, unsigned len) 794 { 795 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 796 y + base_type::filter_dy_dbl(), len); 797 long_type fg[3]; 798 799 int diameter = base_type::filter().diameter(); 800 int filter_scale = diameter << image_subpixel_shift; 801 802 const int16* weight_array = base_type::filter().weight_array(); 803 do 804 { 805 int rx; 806 int ry; 807 int rx_inv = image_subpixel_scale; 808 int ry_inv = image_subpixel_scale; 809 base_type::interpolator().coordinates(&x, &y); 810 base_type::interpolator().local_scale(&rx, &ry); 811 base_type::adjust_scale(&rx, &ry); 812 813 rx_inv = image_subpixel_scale * image_subpixel_scale / rx; 814 ry_inv = image_subpixel_scale * image_subpixel_scale / ry; 815 816 int radius_x = (diameter * rx) >> 1; 817 int radius_y = (diameter * ry) >> 1; 818 int len_x_lr = 819 (diameter * rx + image_subpixel_mask) >> 820 image_subpixel_shift; 821 822 x += base_type::filter_dx_int() - radius_x; 823 y += base_type::filter_dy_int() - radius_y; 824 825 fg[0] = fg[1] = fg[2] = image_filter_scale / 2; 826 827 int y_lr = y >> image_subpixel_shift; 828 int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * 829 ry_inv) >> 830 image_subpixel_shift; 831 int total_weight = 0; 832 int x_lr = x >> image_subpixel_shift; 833 int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * 834 rx_inv) >> 835 image_subpixel_shift; 836 int x_hr2 = x_hr; 837 const value_type* fg_ptr = 838 (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); 839 840 for(;;) 841 { 842 int weight_y = weight_array[y_hr]; 843 x_hr = x_hr2; 844 for(;;) 845 { 846 int weight = (weight_y * weight_array[x_hr] + 847 image_filter_scale / 2) >> 848 downscale_shift; 849 fg[0] += *fg_ptr++ * weight; 850 fg[1] += *fg_ptr++ * weight; 851 fg[2] += *fg_ptr * weight; 852 total_weight += weight; 853 x_hr += rx_inv; 854 if(x_hr >= filter_scale) break; 855 fg_ptr = (const value_type*)base_type::source().next_x(); 856 } 857 y_hr += ry_inv; 858 if(y_hr >= filter_scale) break; 859 fg_ptr = (const value_type*)base_type::source().next_y(); 860 } 861 862 fg[0] /= total_weight; 863 fg[1] /= total_weight; 864 fg[2] /= total_weight; 865 866 if(fg[0] < 0) fg[0] = 0; 867 if(fg[1] < 0) fg[1] = 0; 868 if(fg[2] < 0) fg[2] = 0; 869 870 if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; 871 if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; 872 if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; 873 874 span->r = (value_type)fg[order_type::R]; 875 span->g = (value_type)fg[order_type::G]; 876 span->b = (value_type)fg[order_type::B]; 877 span->a = base_mask; 878 879 ++span; 880 ++base_type::interpolator(); 881 } while(--len); 882 } 883 }; 884 885 886} 887 888 889#endif 890 891 892 893