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