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