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_GRAY_INCLUDED 24#define AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED 25 26#include "agg_basics.h" 27#include "agg_color_gray.h" 28#include "agg_span_image_filter.h" 29 30 31namespace agg 32{ 33 34 //==============================================span_image_filter_gray_nn 35 template<class Source, class Interpolator> 36 class span_image_filter_gray_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 Interpolator interpolator_type; 43 typedef span_image_filter<source_type, interpolator_type> base_type; 44 typedef typename color_type::value_type value_type; 45 typedef typename color_type::calc_type calc_type; 46 enum base_scale_e 47 { 48 base_shift = color_type::base_shift, 49 base_mask = color_type::base_mask 50 }; 51 52 //-------------------------------------------------------------------- 53 span_image_filter_gray_nn() {} 54 span_image_filter_gray_nn(source_type& src, 55 interpolator_type& inter) : 56 base_type(src, inter, 0) 57 {} 58 59 //-------------------------------------------------------------------- 60 void generate(color_type* span, int x, int y, unsigned len) 61 { 62 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 63 y + base_type::filter_dy_dbl(), len); 64 do 65 { 66 base_type::interpolator().coordinates(&x, &y); 67 span->v = *(const value_type*) 68 base_type::source().span(x >> image_subpixel_shift, 69 y >> image_subpixel_shift, 70 1); 71 span->a = base_mask; 72 ++span; 73 ++base_type::interpolator(); 74 } while(--len); 75 } 76 }; 77 78 79 80 //=========================================span_image_filter_gray_bilinear 81 template<class Source, class Interpolator> 82 class span_image_filter_gray_bilinear : 83 public span_image_filter<Source, Interpolator> 84 { 85 public: 86 typedef Source source_type; 87 typedef typename source_type::color_type color_type; 88 typedef Interpolator interpolator_type; 89 typedef span_image_filter<source_type, interpolator_type> base_type; 90 typedef typename color_type::value_type value_type; 91 typedef typename color_type::calc_type calc_type; 92 enum base_scale_e 93 { 94 base_shift = color_type::base_shift, 95 base_mask = color_type::base_mask 96 }; 97 98 //-------------------------------------------------------------------- 99 span_image_filter_gray_bilinear() {} 100 span_image_filter_gray_bilinear(source_type& src, 101 interpolator_type& inter) : 102 base_type(src, inter, 0) 103 {} 104 105 106 //-------------------------------------------------------------------- 107 void generate(color_type* span, int x, int y, unsigned len) 108 { 109 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 110 y + base_type::filter_dy_dbl(), len); 111 calc_type fg; 112 const value_type *fg_ptr; 113 do 114 { 115 int x_hr; 116 int y_hr; 117 118 base_type::interpolator().coordinates(&x_hr, &y_hr); 119 120 x_hr -= base_type::filter_dx_int(); 121 y_hr -= base_type::filter_dy_int(); 122 123 int x_lr = x_hr >> image_subpixel_shift; 124 int y_lr = y_hr >> image_subpixel_shift; 125 126 fg = image_subpixel_scale * image_subpixel_scale / 2; 127 128 x_hr &= image_subpixel_mask; 129 y_hr &= image_subpixel_mask; 130 131 fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); 132 fg += *fg_ptr * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); 133 134 fg_ptr = (const value_type*)base_type::source().next_x(); 135 fg += *fg_ptr * x_hr * (image_subpixel_scale - y_hr); 136 137 fg_ptr = (const value_type*)base_type::source().next_y(); 138 fg += *fg_ptr * (image_subpixel_scale - x_hr) * y_hr; 139 140 fg_ptr = (const value_type*)base_type::source().next_x(); 141 fg += *fg_ptr * x_hr * y_hr; 142 143 span->v = value_type(fg >> (image_subpixel_shift * 2)); 144 span->a = base_mask; 145 ++span; 146 ++base_type::interpolator(); 147 148 } while(--len); 149 } 150 }; 151 152 153 //====================================span_image_filter_gray_bilinear_clip 154 template<class Source, class Interpolator> 155 class span_image_filter_gray_bilinear_clip : 156 public span_image_filter<Source, Interpolator> 157 { 158 public: 159 typedef Source source_type; 160 typedef typename source_type::color_type color_type; 161 typedef Interpolator interpolator_type; 162 typedef span_image_filter<source_type, interpolator_type> base_type; 163 typedef typename color_type::value_type value_type; 164 typedef typename color_type::calc_type calc_type; 165 enum base_scale_e 166 { 167 base_shift = color_type::base_shift, 168 base_mask = color_type::base_mask 169 }; 170 171 //-------------------------------------------------------------------- 172 span_image_filter_gray_bilinear_clip() {} 173 span_image_filter_gray_bilinear_clip(source_type& src, 174 const color_type& back_color, 175 interpolator_type& inter) : 176 base_type(src, inter, 0), 177 m_back_color(back_color) 178 {} 179 const color_type& background_color() const { return m_back_color; } 180 void background_color(const color_type& v) { m_back_color = v; } 181 182 //-------------------------------------------------------------------- 183 void generate(color_type* span, int x, int y, unsigned len) 184 { 185 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 186 y + base_type::filter_dy_dbl(), len); 187 calc_type fg; 188 calc_type src_alpha; 189 value_type back_v = m_back_color.v; 190 value_type back_a = m_back_color.a; 191 192 const value_type *fg_ptr; 193 194 int maxx = base_type::source().width() - 1; 195 int maxy = base_type::source().height() - 1; 196 197 do 198 { 199 int x_hr; 200 int y_hr; 201 202 base_type::interpolator().coordinates(&x_hr, &y_hr); 203 204 x_hr -= base_type::filter_dx_int(); 205 y_hr -= base_type::filter_dy_int(); 206 207 int x_lr = x_hr >> image_subpixel_shift; 208 int y_lr = y_hr >> image_subpixel_shift; 209 210 if(x_lr >= 0 && y_lr >= 0 && 211 x_lr < maxx && y_lr < maxy) 212 { 213 fg = image_subpixel_scale * image_subpixel_scale / 2; 214 215 x_hr &= image_subpixel_mask; 216 y_hr &= image_subpixel_mask; 217 fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr; 218 219 fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); 220 fg += *fg_ptr++ * (image_subpixel_scale - y_hr) * x_hr; 221 222 ++y_lr; 223 fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr; 224 225 fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * y_hr; 226 fg += *fg_ptr++ * x_hr * y_hr; 227 228 fg >>= image_subpixel_shift * 2; 229 src_alpha = base_mask; 230 } 231 else 232 { 233 unsigned weight; 234 if(x_lr < -1 || y_lr < -1 || 235 x_lr > maxx || y_lr > maxy) 236 { 237 fg = back_v; 238 src_alpha = back_a; 239 } 240 else 241 { 242 fg = 243 src_alpha = image_subpixel_scale * image_subpixel_scale / 2; 244 245 x_hr &= image_subpixel_mask; 246 y_hr &= image_subpixel_mask; 247 248 weight = (image_subpixel_scale - x_hr) * 249 (image_subpixel_scale - y_hr); 250 if(x_lr >= 0 && y_lr >= 0 && 251 x_lr <= maxx && y_lr <= maxy) 252 { 253 fg += weight * 254 *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); 255 src_alpha += weight * base_mask; 256 } 257 else 258 { 259 fg += back_v * weight; 260 src_alpha += back_a * weight; 261 } 262 263 x_lr++; 264 265 weight = x_hr * (image_subpixel_scale - y_hr); 266 if(x_lr >= 0 && y_lr >= 0 && 267 x_lr <= maxx && y_lr <= maxy) 268 { 269 fg += weight * 270 *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); 271 src_alpha += weight * base_mask; 272 } 273 else 274 { 275 fg += back_v * weight; 276 src_alpha += back_a * weight; 277 } 278 279 x_lr--; 280 y_lr++; 281 282 weight = (image_subpixel_scale - x_hr) * y_hr; 283 if(x_lr >= 0 && y_lr >= 0 && 284 x_lr <= maxx && y_lr <= maxy) 285 { 286 fg += weight * 287 *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); 288 src_alpha += weight * base_mask; 289 } 290 else 291 { 292 fg += back_v * weight; 293 src_alpha += back_a * weight; 294 } 295 296 x_lr++; 297 298 weight = x_hr * y_hr; 299 if(x_lr >= 0 && y_lr >= 0 && 300 x_lr <= maxx && y_lr <= maxy) 301 { 302 fg += weight * 303 *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); 304 src_alpha += weight * base_mask; 305 } 306 else 307 { 308 fg += back_v * weight; 309 src_alpha += back_a * weight; 310 } 311 312 fg >>= image_subpixel_shift * 2; 313 src_alpha >>= image_subpixel_shift * 2; 314 } 315 } 316 317 span->v = (value_type)fg; 318 span->a = (value_type)src_alpha; 319 ++span; 320 ++base_type::interpolator(); 321 322 } while(--len); 323 } 324 private: 325 color_type m_back_color; 326 }; 327 328 329 330 //==============================================span_image_filter_gray_2x2 331 template<class Source, class Interpolator> 332 class span_image_filter_gray_2x2 : 333 public span_image_filter<Source, Interpolator> 334 { 335 public: 336 typedef Source source_type; 337 typedef typename source_type::color_type color_type; 338 typedef Interpolator interpolator_type; 339 typedef span_image_filter<source_type, interpolator_type> base_type; 340 typedef typename color_type::value_type value_type; 341 typedef typename color_type::calc_type calc_type; 342 enum base_scale_e 343 { 344 base_shift = color_type::base_shift, 345 base_mask = color_type::base_mask 346 }; 347 348 //-------------------------------------------------------------------- 349 span_image_filter_gray_2x2() {} 350 span_image_filter_gray_2x2(source_type& src, 351 interpolator_type& inter, 352 const image_filter_lut& filter) : 353 base_type(src, inter, &filter) 354 {} 355 356 357 //-------------------------------------------------------------------- 358 void generate(color_type* span, int x, int y, unsigned len) 359 { 360 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 361 y + base_type::filter_dy_dbl(), len); 362 363 calc_type fg; 364 365 const value_type *fg_ptr; 366 const int16* weight_array = base_type::filter().weight_array() + 367 ((base_type::filter().diameter()/2 - 1) << 368 image_subpixel_shift); 369 do 370 { 371 int x_hr; 372 int y_hr; 373 374 base_type::interpolator().coordinates(&x_hr, &y_hr); 375 376 x_hr -= base_type::filter_dx_int(); 377 y_hr -= base_type::filter_dy_int(); 378 379 int x_lr = x_hr >> image_subpixel_shift; 380 int y_lr = y_hr >> image_subpixel_shift; 381 382 unsigned weight; 383 fg = image_filter_scale / 2; 384 385 x_hr &= image_subpixel_mask; 386 y_hr &= image_subpixel_mask; 387 388 fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); 389 weight = (weight_array[x_hr + image_subpixel_scale] * 390 weight_array[y_hr + image_subpixel_scale] + 391 image_filter_scale / 2) >> 392 image_filter_shift; 393 fg += weight * *fg_ptr; 394 395 fg_ptr = (const value_type*)base_type::source().next_x(); 396 weight = (weight_array[x_hr] * 397 weight_array[y_hr + image_subpixel_scale] + 398 image_filter_scale / 2) >> 399 image_filter_shift; 400 fg += weight * *fg_ptr; 401 402 fg_ptr = (const value_type*)base_type::source().next_y(); 403 weight = (weight_array[x_hr + image_subpixel_scale] * 404 weight_array[y_hr] + 405 image_filter_scale / 2) >> 406 image_filter_shift; 407 fg += weight * *fg_ptr; 408 409 fg_ptr = (const value_type*)base_type::source().next_x(); 410 weight = (weight_array[x_hr] * 411 weight_array[y_hr] + 412 image_filter_scale / 2) >> 413 image_filter_shift; 414 fg += weight * *fg_ptr; 415 416 fg >>= image_filter_shift; 417 if(fg > base_mask) fg = base_mask; 418 419 span->v = (value_type)fg; 420 span->a = base_mask; 421 ++span; 422 ++base_type::interpolator(); 423 } while(--len); 424 } 425 }; 426 427 428 429 //==================================================span_image_filter_gray 430 template<class Source, class Interpolator> 431 class span_image_filter_gray : 432 public span_image_filter<Source, Interpolator> 433 { 434 public: 435 typedef Source source_type; 436 typedef typename source_type::color_type color_type; 437 typedef Interpolator interpolator_type; 438 typedef span_image_filter<source_type, interpolator_type> base_type; 439 typedef typename color_type::value_type value_type; 440 typedef typename color_type::calc_type calc_type; 441 enum base_scale_e 442 { 443 base_shift = color_type::base_shift, 444 base_mask = color_type::base_mask 445 }; 446 447 //-------------------------------------------------------------------- 448 span_image_filter_gray() {} 449 span_image_filter_gray(source_type& src, 450 interpolator_type& inter, 451 const image_filter_lut& filter) : 452 base_type(src, inter, &filter) 453 {} 454 455 //-------------------------------------------------------------------- 456 void generate(color_type* span, int x, int y, unsigned len) 457 { 458 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 459 y + base_type::filter_dy_dbl(), len); 460 461 int fg; 462 const value_type *fg_ptr; 463 464 unsigned diameter = base_type::filter().diameter(); 465 int start = base_type::filter().start(); 466 const int16* weight_array = base_type::filter().weight_array(); 467 468 int x_count; 469 int weight_y; 470 471 do 472 { 473 base_type::interpolator().coordinates(&x, &y); 474 475 x -= base_type::filter_dx_int(); 476 y -= base_type::filter_dy_int(); 477 478 int x_hr = x; 479 int y_hr = y; 480 481 int x_lr = x_hr >> image_subpixel_shift; 482 int y_lr = y_hr >> image_subpixel_shift; 483 484 fg = image_filter_scale / 2; 485 486 int x_fract = x_hr & image_subpixel_mask; 487 unsigned y_count = diameter; 488 489 y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); 490 fg_ptr = (const value_type*)base_type::source().span(x_lr + start, 491 y_lr + start, 492 diameter); 493 for(;;) 494 { 495 x_count = diameter; 496 weight_y = weight_array[y_hr]; 497 x_hr = image_subpixel_mask - x_fract; 498 for(;;) 499 { 500 fg += *fg_ptr * 501 ((weight_y * weight_array[x_hr] + 502 image_filter_scale / 2) >> 503 image_filter_shift); 504 if(--x_count == 0) break; 505 x_hr += image_subpixel_scale; 506 fg_ptr = (const value_type*)base_type::source().next_x(); 507 } 508 509 if(--y_count == 0) break; 510 y_hr += image_subpixel_scale; 511 fg_ptr = (const value_type*)base_type::source().next_y(); 512 } 513 514 fg >>= image_filter_shift; 515 if(fg < 0) fg = 0; 516 if(fg > base_mask) fg = base_mask; 517 span->v = (value_type)fg; 518 span->a = base_mask; 519 520 ++span; 521 ++base_type::interpolator(); 522 523 } while(--len); 524 } 525 }; 526 527 528 529 //=========================================span_image_resample_gray_affine 530 template<class Source> 531 class span_image_resample_gray_affine : 532 public span_image_resample_affine<Source> 533 { 534 public: 535 typedef Source source_type; 536 typedef typename source_type::color_type color_type; 537 typedef span_image_resample_affine<source_type> base_type; 538 typedef typename base_type::interpolator_type interpolator_type; 539 typedef typename color_type::value_type value_type; 540 typedef typename color_type::long_type long_type; 541 enum base_scale_e 542 { 543 base_shift = color_type::base_shift, 544 base_mask = color_type::base_mask, 545 downscale_shift = image_filter_shift 546 }; 547 548 //-------------------------------------------------------------------- 549 span_image_resample_gray_affine() {} 550 span_image_resample_gray_affine(source_type& src, 551 interpolator_type& inter, 552 const image_filter_lut& filter) : 553 base_type(src, inter, filter) 554 {} 555 556 557 //-------------------------------------------------------------------- 558 void generate(color_type* span, int x, int y, unsigned len) 559 { 560 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 561 y + base_type::filter_dy_dbl(), len); 562 563 long_type fg; 564 565 int diameter = base_type::filter().diameter(); 566 int filter_scale = diameter << image_subpixel_shift; 567 int radius_x = (diameter * base_type::m_rx) >> 1; 568 int radius_y = (diameter * base_type::m_ry) >> 1; 569 int len_x_lr = 570 (diameter * base_type::m_rx + image_subpixel_mask) >> 571 image_subpixel_shift; 572 573 const int16* weight_array = base_type::filter().weight_array(); 574 575 do 576 { 577 base_type::interpolator().coordinates(&x, &y); 578 579 x += base_type::filter_dx_int() - radius_x; 580 y += base_type::filter_dy_int() - radius_y; 581 582 fg = image_filter_scale / 2; 583 584 int y_lr = y >> image_subpixel_shift; 585 int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * 586 base_type::m_ry_inv) >> 587 image_subpixel_shift; 588 int total_weight = 0; 589 int x_lr = x >> image_subpixel_shift; 590 int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * 591 base_type::m_rx_inv) >> 592 image_subpixel_shift; 593 594 int x_hr2 = x_hr; 595 const value_type* fg_ptr = 596 (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); 597 for(;;) 598 { 599 int weight_y = weight_array[y_hr]; 600 x_hr = x_hr2; 601 for(;;) 602 { 603 int weight = (weight_y * weight_array[x_hr] + 604 image_filter_scale / 2) >> 605 downscale_shift; 606 607 fg += *fg_ptr * weight; 608 total_weight += weight; 609 x_hr += base_type::m_rx_inv; 610 if(x_hr >= filter_scale) break; 611 fg_ptr = (const value_type*)base_type::source().next_x(); 612 } 613 y_hr += base_type::m_ry_inv; 614 if(y_hr >= filter_scale) break; 615 fg_ptr = (const value_type*)base_type::source().next_y(); 616 } 617 618 fg /= total_weight; 619 if(fg < 0) fg = 0; 620 if(fg > base_mask) fg = base_mask; 621 622 span->v = (value_type)fg; 623 span->a = base_mask; 624 625 ++span; 626 ++base_type::interpolator(); 627 } while(--len); 628 } 629 }; 630 631 632 633 //================================================span_image_resample_gray 634 template<class Source, class Interpolator> 635 class span_image_resample_gray : 636 public span_image_resample<Source, Interpolator> 637 { 638 public: 639 typedef Source source_type; 640 typedef typename source_type::color_type color_type; 641 typedef Interpolator interpolator_type; 642 typedef span_image_resample<source_type, interpolator_type> base_type; 643 typedef typename color_type::value_type value_type; 644 typedef typename color_type::long_type long_type; 645 enum base_scale_e 646 { 647 base_shift = color_type::base_shift, 648 base_mask = color_type::base_mask, 649 downscale_shift = image_filter_shift 650 }; 651 652 //-------------------------------------------------------------------- 653 span_image_resample_gray() {} 654 span_image_resample_gray(source_type& src, 655 interpolator_type& inter, 656 const image_filter_lut& filter) : 657 base_type(src, inter, filter) 658 {} 659 660 //-------------------------------------------------------------------- 661 void generate(color_type* span, int x, int y, unsigned len) 662 { 663 base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 664 y + base_type::filter_dy_dbl(), len); 665 long_type fg; 666 667 int diameter = base_type::filter().diameter(); 668 int filter_scale = diameter << image_subpixel_shift; 669 670 const int16* weight_array = base_type::filter().weight_array(); 671 do 672 { 673 int rx; 674 int ry; 675 int rx_inv = image_subpixel_scale; 676 int ry_inv = image_subpixel_scale; 677 base_type::interpolator().coordinates(&x, &y); 678 base_type::interpolator().local_scale(&rx, &ry); 679 base_type::adjust_scale(&rx, &ry); 680 681 rx_inv = image_subpixel_scale * image_subpixel_scale / rx; 682 ry_inv = image_subpixel_scale * image_subpixel_scale / ry; 683 684 int radius_x = (diameter * rx) >> 1; 685 int radius_y = (diameter * ry) >> 1; 686 int len_x_lr = 687 (diameter * rx + image_subpixel_mask) >> 688 image_subpixel_shift; 689 690 x += base_type::filter_dx_int() - radius_x; 691 y += base_type::filter_dy_int() - radius_y; 692 693 fg = image_filter_scale / 2; 694 695 int y_lr = y >> image_subpixel_shift; 696 int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * 697 ry_inv) >> 698 image_subpixel_shift; 699 int total_weight = 0; 700 int x_lr = x >> image_subpixel_shift; 701 int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * 702 rx_inv) >> 703 image_subpixel_shift; 704 int x_hr2 = x_hr; 705 const value_type* fg_ptr = 706 (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); 707 708 for(;;) 709 { 710 int weight_y = weight_array[y_hr]; 711 x_hr = x_hr2; 712 for(;;) 713 { 714 int weight = (weight_y * weight_array[x_hr] + 715 image_filter_scale / 2) >> 716 downscale_shift; 717 fg += *fg_ptr * weight; 718 total_weight += weight; 719 x_hr += rx_inv; 720 if(x_hr >= filter_scale) break; 721 fg_ptr = (const value_type*)base_type::source().next_x(); 722 } 723 y_hr += ry_inv; 724 if(y_hr >= filter_scale) break; 725 fg_ptr = (const value_type*)base_type::source().next_y(); 726 } 727 728 fg /= total_weight; 729 if(fg < 0) fg = 0; 730 if(fg > base_mask) fg = base_mask; 731 732 span->v = (value_type)fg; 733 span->a = base_mask; 734 735 ++span; 736 ++base_type::interpolator(); 737 } while(--len); 738 } 739 }; 740 741 742} 743 744 745#endif 746 747 748 749