1 /* -*- mode: c++; c-basic-offset: 4 -*- */
2
3 #ifndef RESAMPLE_H
4 #define RESAMPLE_H
5
6 #include "agg_image_accessors.h"
7 #include "agg_path_storage.h"
8 #include "agg_pixfmt_gray.h"
9 #include "agg_pixfmt_rgb.h"
10 #include "agg_pixfmt_rgba.h"
11 #include "agg_renderer_base.h"
12 #include "agg_renderer_scanline.h"
13 #include "agg_rasterizer_scanline_aa.h"
14 #include "agg_scanline_u.h"
15 #include "agg_span_allocator.h"
16 #include "agg_span_converter.h"
17 #include "agg_span_image_filter_gray.h"
18 #include "agg_span_image_filter_rgba.h"
19 #include "agg_span_interpolator_adaptor.h"
20 #include "agg_span_interpolator_linear.h"
21
22 #include "agg_workaround.h"
23
24 // Based on:
25
26 //----------------------------------------------------------------------------
27 // Anti-Grain Geometry - Version 2.4
28 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
29 //
30 // Permission to copy, use, modify, sell and distribute this software
31 // is granted provided this copyright notice appears in all copies.
32 // This software is provided "as is" without express or implied
33 // warranty, and with no claim as to its suitability for any purpose.
34 //
35 //----------------------------------------------------------------------------
36 // Contact: mcseem@antigrain.com
37 // mcseemagg@yahoo.com
38 // http://www.antigrain.com
39 //----------------------------------------------------------------------------
40 //
41 // Adaptation for high precision colors has been sponsored by
42 // Liberty Technology Systems, Inc., visit http://lib-sys.com
43 //
44 // Liberty Technology Systems, Inc. is the provider of
45 // PostScript and PDF technology for software developers.
46 //
47
48 //===================================================================gray64
49 namespace agg
50 {
51 struct gray64
52 {
53 typedef double value_type;
54 typedef double calc_type;
55 typedef double long_type;
56 typedef gray64 self_type;
57
58 value_type v;
59 value_type a;
60
61 //--------------------------------------------------------------------
gray64gray6462 gray64() {}
63
64 //--------------------------------------------------------------------
65 explicit gray64(value_type v_, value_type a_ = 1) :
vgray6466 v(v_), a(a_) {}
67
68 //--------------------------------------------------------------------
gray64gray6469 gray64(const self_type& c, value_type a_) :
70 v(c.v), a(a_) {}
71
72 //--------------------------------------------------------------------
gray64gray6473 gray64(const gray64& c) :
74 v(c.v),
75 a(c.a) {}
76
77 //--------------------------------------------------------------------
to_doublegray6478 static AGG_INLINE double to_double(value_type a)
79 {
80 return a;
81 }
82
83 //--------------------------------------------------------------------
from_doublegray6484 static AGG_INLINE value_type from_double(double a)
85 {
86 return value_type(a);
87 }
88
89 //--------------------------------------------------------------------
empty_valuegray6490 static AGG_INLINE value_type empty_value()
91 {
92 return 0;
93 }
94
95 //--------------------------------------------------------------------
full_valuegray6496 static AGG_INLINE value_type full_value()
97 {
98 return 1;
99 }
100
101 //--------------------------------------------------------------------
is_transparentgray64102 AGG_INLINE bool is_transparent() const
103 {
104 return a <= 0;
105 }
106
107 //--------------------------------------------------------------------
is_opaquegray64108 AGG_INLINE bool is_opaque() const
109 {
110 return a >= 1;
111 }
112
113 //--------------------------------------------------------------------
invertgray64114 static AGG_INLINE value_type invert(value_type x)
115 {
116 return 1 - x;
117 }
118
119 //--------------------------------------------------------------------
multiplygray64120 static AGG_INLINE value_type multiply(value_type a, value_type b)
121 {
122 return value_type(a * b);
123 }
124
125 //--------------------------------------------------------------------
demultiplygray64126 static AGG_INLINE value_type demultiply(value_type a, value_type b)
127 {
128 return (b == 0) ? 0 : value_type(a / b);
129 }
130
131 //--------------------------------------------------------------------
132 template<typename T>
downscalegray64133 static AGG_INLINE T downscale(T a)
134 {
135 return a;
136 }
137
138 //--------------------------------------------------------------------
139 template<typename T>
downshiftgray64140 static AGG_INLINE T downshift(T a, unsigned n)
141 {
142 return n > 0 ? a / (1 << n) : a;
143 }
144
145 //--------------------------------------------------------------------
mult_covergray64146 static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
147 {
148 return value_type(a * b / cover_mask);
149 }
150
151 //--------------------------------------------------------------------
scale_covergray64152 static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
153 {
154 return cover_type(uround(a * b));
155 }
156
157 //--------------------------------------------------------------------
158 // Interpolate p to q by a, assuming q is premultiplied by a.
prelerpgray64159 static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
160 {
161 return (1 - a) * p + q; // more accurate than "p + q - p * a"
162 }
163
164 //--------------------------------------------------------------------
165 // Interpolate p to q by a.
lerpgray64166 static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
167 {
168 // The form "p + a * (q - p)" avoids a multiplication, but may produce an
169 // inaccurate result. For example, "p + (q - p)" may not be exactly equal
170 // to q. Therefore, stick to the basic expression, which at least produces
171 // the correct result at either extreme.
172 return (1 - a) * p + a * q;
173 }
174
175 //--------------------------------------------------------------------
cleargray64176 self_type& clear()
177 {
178 v = a = 0;
179 return *this;
180 }
181
182 //--------------------------------------------------------------------
transparentgray64183 self_type& transparent()
184 {
185 a = 0;
186 return *this;
187 }
188
189 //--------------------------------------------------------------------
opacitygray64190 self_type& opacity(double a_)
191 {
192 if (a_ < 0) a = 0;
193 else if (a_ > 1) a = 1;
194 else a = value_type(a_);
195 return *this;
196 }
197
198 //--------------------------------------------------------------------
opacitygray64199 double opacity() const
200 {
201 return a;
202 }
203
204
205 //--------------------------------------------------------------------
premultiplygray64206 self_type& premultiply()
207 {
208 if (a < 0) v = 0;
209 else if(a < 1) v *= a;
210 return *this;
211 }
212
213 //--------------------------------------------------------------------
demultiplygray64214 self_type& demultiply()
215 {
216 if (a < 0) v = 0;
217 else if (a < 1) v /= a;
218 return *this;
219 }
220
221 //--------------------------------------------------------------------
gradientgray64222 self_type gradient(self_type c, double k) const
223 {
224 return self_type(
225 value_type(v + (c.v - v) * k),
226 value_type(a + (c.a - a) * k));
227 }
228
229 //--------------------------------------------------------------------
no_colorgray64230 static self_type no_color() { return self_type(0,0); }
231 };
232
233
234 //====================================================================rgba32
235 struct rgba64
236 {
237 typedef double value_type;
238 typedef double calc_type;
239 typedef double long_type;
240 typedef rgba64 self_type;
241
242 value_type r;
243 value_type g;
244 value_type b;
245 value_type a;
246
247 //--------------------------------------------------------------------
rgba64rgba64248 rgba64() {}
249
250 //--------------------------------------------------------------------
251 rgba64(value_type r_, value_type g_, value_type b_, value_type a_= 1) :
rrgba64252 r(r_), g(g_), b(b_), a(a_) {}
253
254 //--------------------------------------------------------------------
rgba64rgba64255 rgba64(const self_type& c, float a_) :
256 r(c.r), g(c.g), b(c.b), a(a_) {}
257
258 //--------------------------------------------------------------------
rgba64rgba64259 rgba64(const rgba& c) :
260 r(value_type(c.r)), g(value_type(c.g)), b(value_type(c.b)), a(value_type(c.a)) {}
261
262 //--------------------------------------------------------------------
rgbargba64263 operator rgba() const
264 {
265 return rgba(r, g, b, a);
266 }
267
268 //--------------------------------------------------------------------
to_doublergba64269 static AGG_INLINE double to_double(value_type a)
270 {
271 return a;
272 }
273
274 //--------------------------------------------------------------------
from_doublergba64275 static AGG_INLINE value_type from_double(double a)
276 {
277 return value_type(a);
278 }
279
280 //--------------------------------------------------------------------
empty_valuergba64281 static AGG_INLINE value_type empty_value()
282 {
283 return 0;
284 }
285
286 //--------------------------------------------------------------------
full_valuergba64287 static AGG_INLINE value_type full_value()
288 {
289 return 1;
290 }
291
292 //--------------------------------------------------------------------
is_transparentrgba64293 AGG_INLINE bool is_transparent() const
294 {
295 return a <= 0;
296 }
297
298 //--------------------------------------------------------------------
is_opaquergba64299 AGG_INLINE bool is_opaque() const
300 {
301 return a >= 1;
302 }
303
304 //--------------------------------------------------------------------
invertrgba64305 static AGG_INLINE value_type invert(value_type x)
306 {
307 return 1 - x;
308 }
309
310 //--------------------------------------------------------------------
multiplyrgba64311 static AGG_INLINE value_type multiply(value_type a, value_type b)
312 {
313 return value_type(a * b);
314 }
315
316 //--------------------------------------------------------------------
demultiplyrgba64317 static AGG_INLINE value_type demultiply(value_type a, value_type b)
318 {
319 return (b == 0) ? 0 : value_type(a / b);
320 }
321
322 //--------------------------------------------------------------------
323 template<typename T>
downscalergba64324 static AGG_INLINE T downscale(T a)
325 {
326 return a;
327 }
328
329 //--------------------------------------------------------------------
330 template<typename T>
downshiftrgba64331 static AGG_INLINE T downshift(T a, unsigned n)
332 {
333 return n > 0 ? a / (1 << n) : a;
334 }
335
336 //--------------------------------------------------------------------
mult_coverrgba64337 static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
338 {
339 return value_type(a * b / cover_mask);
340 }
341
342 //--------------------------------------------------------------------
scale_coverrgba64343 static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
344 {
345 return cover_type(uround(a * b));
346 }
347
348 //--------------------------------------------------------------------
349 // Interpolate p to q by a, assuming q is premultiplied by a.
prelerprgba64350 static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
351 {
352 return (1 - a) * p + q; // more accurate than "p + q - p * a"
353 }
354
355 //--------------------------------------------------------------------
356 // Interpolate p to q by a.
lerprgba64357 static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
358 {
359 // The form "p + a * (q - p)" avoids a multiplication, but may produce an
360 // inaccurate result. For example, "p + (q - p)" may not be exactly equal
361 // to q. Therefore, stick to the basic expression, which at least produces
362 // the correct result at either extreme.
363 return (1 - a) * p + a * q;
364 }
365
366 //--------------------------------------------------------------------
clearrgba64367 self_type& clear()
368 {
369 r = g = b = a = 0;
370 return *this;
371 }
372
373 //--------------------------------------------------------------------
transparentrgba64374 self_type& transparent()
375 {
376 a = 0;
377 return *this;
378 }
379
380 //--------------------------------------------------------------------
opacityrgba64381 AGG_INLINE self_type& opacity(double a_)
382 {
383 if (a_ < 0) a = 0;
384 else if (a_ > 1) a = 1;
385 else a = value_type(a_);
386 return *this;
387 }
388
389 //--------------------------------------------------------------------
opacityrgba64390 double opacity() const
391 {
392 return a;
393 }
394
395 //--------------------------------------------------------------------
premultiplyrgba64396 AGG_INLINE self_type& premultiply()
397 {
398 if (a < 1)
399 {
400 if (a <= 0)
401 {
402 r = g = b = 0;
403 }
404 else
405 {
406 r *= a;
407 g *= a;
408 b *= a;
409 }
410 }
411 return *this;
412 }
413
414 //--------------------------------------------------------------------
demultiplyrgba64415 AGG_INLINE self_type& demultiply()
416 {
417 if (a < 1)
418 {
419 if (a <= 0)
420 {
421 r = g = b = 0;
422 }
423 else
424 {
425 r /= a;
426 g /= a;
427 b /= a;
428 }
429 }
430 return *this;
431 }
432
433 //--------------------------------------------------------------------
gradientrgba64434 AGG_INLINE self_type gradient(const self_type& c, double k) const
435 {
436 self_type ret;
437 ret.r = value_type(r + (c.r - r) * k);
438 ret.g = value_type(g + (c.g - g) * k);
439 ret.b = value_type(b + (c.b - b) * k);
440 ret.a = value_type(a + (c.a - a) * k);
441 return ret;
442 }
443
444 //--------------------------------------------------------------------
addrgba64445 AGG_INLINE void add(const self_type& c, unsigned cover)
446 {
447 if (cover == cover_mask)
448 {
449 if (c.is_opaque())
450 {
451 *this = c;
452 return;
453 }
454 else
455 {
456 r += c.r;
457 g += c.g;
458 b += c.b;
459 a += c.a;
460 }
461 }
462 else
463 {
464 r += mult_cover(c.r, cover);
465 g += mult_cover(c.g, cover);
466 b += mult_cover(c.b, cover);
467 a += mult_cover(c.a, cover);
468 }
469 if (a > 1) a = 1;
470 if (r > a) r = a;
471 if (g > a) g = a;
472 if (b > a) b = a;
473 }
474
475 //--------------------------------------------------------------------
no_colorrgba64476 static self_type no_color() { return self_type(0,0,0,0); }
477 };
478 }
479
480
481 typedef enum {
482 NEAREST,
483 BILINEAR,
484 BICUBIC,
485 SPLINE16,
486 SPLINE36,
487 HANNING,
488 HAMMING,
489 HERMITE,
490 KAISER,
491 QUADRIC,
492 CATROM,
493 GAUSSIAN,
494 BESSEL,
495 MITCHELL,
496 SINC,
497 LANCZOS,
498 BLACKMAN,
499 _n_interpolation
500 } interpolation_e;
501
502
503 template <typename T>
504 class type_mapping;
505
506
507 template <> class type_mapping<agg::rgba8>
508 {
509 public:
510 typedef agg::rgba8 color_type;
511 typedef fixed_blender_rgba_plain<color_type, agg::order_rgba> blender_type;
512 typedef fixed_blender_rgba_pre<color_type, agg::order_rgba> pre_blender_type;
513 typedef agg::pixfmt_alpha_blend_rgba<blender_type, agg::rendering_buffer> pixfmt_type;
514 typedef agg::pixfmt_alpha_blend_rgba<pre_blender_type, agg::rendering_buffer> pixfmt_pre_type;
515
516 template <typename A>
517 struct span_gen_affine_type
518 {
519 typedef agg::span_image_resample_rgba_affine<A> type;
520 };
521
522 template <typename A, typename B>
523 struct span_gen_filter_type
524 {
525 typedef agg::span_image_filter_rgba<A, B> type;
526 };
527
528 template <typename A, typename B>
529 struct span_gen_nn_type
530 {
531 typedef agg::span_image_filter_rgba_nn<A, B> type;
532 };
533 };
534
535
536 template <> class type_mapping<agg::rgba16>
537 {
538 public:
539 typedef agg::rgba16 color_type;
540 typedef fixed_blender_rgba_plain<color_type, agg::order_rgba> blender_type;
541 typedef fixed_blender_rgba_pre<color_type, agg::order_rgba> pre_blender_type;
542 typedef agg::pixfmt_alpha_blend_rgba<blender_type, agg::rendering_buffer> pixfmt_type;
543 typedef agg::pixfmt_alpha_blend_rgba<pre_blender_type, agg::rendering_buffer> pixfmt_pre_type;
544
545 template <typename A>
546 struct span_gen_affine_type
547 {
548 typedef agg::span_image_resample_rgba_affine<A> type;
549 };
550
551 template <typename A, typename B>
552 struct span_gen_filter_type
553 {
554 typedef agg::span_image_filter_rgba<A, B> type;
555 };
556
557 template <typename A, typename B>
558 struct span_gen_nn_type
559 {
560 typedef agg::span_image_filter_rgba_nn<A, B> type;
561 };
562 };
563
564
565 template <> class type_mapping<agg::rgba32>
566 {
567 public:
568 typedef agg::rgba32 color_type;
569 typedef agg::blender_rgba_plain<color_type, agg::order_rgba> blender_type;
570 typedef agg::blender_rgba_pre<color_type, agg::order_rgba> pre_blender_type;
571 typedef agg::pixfmt_alpha_blend_rgba<blender_type, agg::rendering_buffer> pixfmt_type;
572 typedef agg::pixfmt_alpha_blend_rgba<pre_blender_type, agg::rendering_buffer> pixfmt_pre_type;
573
574 template <typename A>
575 struct span_gen_affine_type
576 {
577 typedef agg::span_image_resample_rgba_affine<A> type;
578 };
579
580 template <typename A, typename B>
581 struct span_gen_filter_type
582 {
583 typedef agg::span_image_filter_rgba<A, B> type;
584 };
585
586 template <typename A, typename B>
587 struct span_gen_nn_type
588 {
589 typedef agg::span_image_filter_rgba_nn<A, B> type;
590 };
591 };
592
593
594 template <> class type_mapping<agg::rgba64>
595 {
596 public:
597 typedef agg::rgba64 color_type;
598 typedef agg::blender_rgba_plain<color_type, agg::order_rgba> blender_type;
599 typedef agg::blender_rgba_pre<color_type, agg::order_rgba> pre_blender_type;
600 typedef agg::pixfmt_alpha_blend_rgba<blender_type, agg::rendering_buffer> pixfmt_type;
601 typedef agg::pixfmt_alpha_blend_rgba<pre_blender_type, agg::rendering_buffer> pixfmt_pre_type;
602
603 template <typename A>
604 struct span_gen_affine_type
605 {
606 typedef agg::span_image_resample_rgba_affine<A> type;
607 };
608
609 template <typename A, typename B>
610 struct span_gen_filter_type
611 {
612 typedef agg::span_image_filter_rgba<A, B> type;
613 };
614
615 template <typename A, typename B>
616 struct span_gen_nn_type
617 {
618 typedef agg::span_image_filter_rgba_nn<A, B> type;
619 };
620 };
621
622
623 template <> class type_mapping<double>
624 {
625 public:
626 typedef agg::gray64 color_type;
627 typedef agg::blender_gray<color_type> blender_type;
628 typedef agg::pixfmt_alpha_blend_gray<blender_type, agg::rendering_buffer> pixfmt_type;
629 typedef pixfmt_type pixfmt_pre_type;
630
631 template <typename A>
632 struct span_gen_affine_type
633 {
634 typedef agg::span_image_resample_gray_affine<A> type;
635 };
636
637 template <typename A, typename B>
638 struct span_gen_filter_type
639 {
640 typedef agg::span_image_filter_gray<A, B> type;
641 };
642
643 template <typename A, typename B>
644 struct span_gen_nn_type
645 {
646 typedef agg::span_image_filter_gray_nn<A, B> type;
647 };
648 };
649
650
651 template <> class type_mapping<float>
652 {
653 public:
654 typedef agg::gray32 color_type;
655 typedef agg::blender_gray<color_type> blender_type;
656 typedef agg::pixfmt_alpha_blend_gray<blender_type, agg::rendering_buffer> pixfmt_type;
657 typedef pixfmt_type pixfmt_pre_type;
658
659 template <typename A>
660 struct span_gen_affine_type
661 {
662 typedef agg::span_image_resample_gray_affine<A> type;
663 };
664
665 template <typename A, typename B>
666 struct span_gen_filter_type
667 {
668 typedef agg::span_image_filter_gray<A, B> type;
669 };
670
671 template <typename A, typename B>
672 struct span_gen_nn_type
673 {
674 typedef agg::span_image_filter_gray_nn<A, B> type;
675 };
676 };
677
678
679 template <> class type_mapping<unsigned short>
680 {
681 public:
682 typedef agg::gray16 color_type;
683 typedef agg::blender_gray<color_type> blender_type;
684 typedef agg::pixfmt_alpha_blend_gray<blender_type, agg::rendering_buffer> pixfmt_type;
685 typedef pixfmt_type pixfmt_pre_type;
686
687 template <typename A>
688 struct span_gen_affine_type
689 {
690 typedef agg::span_image_resample_gray_affine<A> type;
691 };
692
693 template <typename A, typename B>
694 struct span_gen_filter_type
695 {
696 typedef agg::span_image_filter_gray<A, B> type;
697 };
698
699 template <typename A, typename B>
700 struct span_gen_nn_type
701 {
702 typedef agg::span_image_filter_gray_nn<A, B> type;
703 };
704 };
705
706
707 template <> class type_mapping<unsigned char>
708 {
709 public:
710 typedef agg::gray8 color_type;
711 typedef agg::blender_gray<color_type> blender_type;
712 typedef agg::pixfmt_alpha_blend_gray<blender_type, agg::rendering_buffer> pixfmt_type;
713 typedef pixfmt_type pixfmt_pre_type;
714
715 template <typename A>
716 struct span_gen_affine_type
717 {
718 typedef agg::span_image_resample_gray_affine<A> type;
719 };
720
721 template <typename A, typename B>
722 struct span_gen_filter_type
723 {
724 typedef agg::span_image_filter_gray<A, B> type;
725 };
726
727 template <typename A, typename B>
728 struct span_gen_nn_type
729 {
730 typedef agg::span_image_filter_gray_nn<A, B> type;
731 };
732 };
733
734
735
736 template<class color_type>
737 class span_conv_alpha
738 {
739 public:
span_conv_alpha(const double alpha)740 span_conv_alpha(const double alpha) :
741 m_alpha(alpha)
742 {
743 }
744
prepare()745 void prepare() {}
746
generate(color_type * span,int x,int y,unsigned len)747 void generate(color_type* span, int x, int y, unsigned len) const
748 {
749 if (m_alpha != 1.0) {
750 do {
751 span->a *= m_alpha;
752 ++span;
753 } while (--len);
754 }
755 }
756 private:
757
758 const double m_alpha;
759 };
760
761
762 /* A class to use a lookup table for a transformation */
763 class lookup_distortion
764 {
765 public:
lookup_distortion(const double * mesh,int in_width,int in_height,int out_width,int out_height)766 lookup_distortion(const double *mesh, int in_width, int in_height,
767 int out_width, int out_height) :
768 m_mesh(mesh),
769 m_in_width(in_width),
770 m_in_height(in_height),
771 m_out_width(out_width),
772 m_out_height(out_height)
773 {}
774
calculate(int * x,int * y)775 void calculate(int* x, int* y) {
776 if (m_mesh) {
777 double dx = double(*x) / agg::image_subpixel_scale;
778 double dy = double(*y) / agg::image_subpixel_scale;
779 if (dx >= 0 && dx < m_out_width &&
780 dy >= 0 && dy < m_out_height) {
781 const double *coord = m_mesh + (int(dy) * m_out_width + int(dx)) * 2;
782 *x = int(coord[0] * agg::image_subpixel_scale);
783 *y = int(coord[1] * agg::image_subpixel_scale);
784 }
785 }
786 }
787
788 protected:
789 const double *m_mesh;
790 int m_in_width;
791 int m_in_height;
792 int m_out_width;
793 int m_out_height;
794 };
795
796
797 struct resample_params_t {
798 interpolation_e interpolation;
799 bool is_affine;
800 agg::trans_affine affine;
801 const double *transform_mesh;
802 bool resample;
803 double norm;
804 double radius;
805 double alpha;
806 };
807
808
get_filter(const resample_params_t & params,agg::image_filter_lut & filter)809 static void get_filter(const resample_params_t ¶ms,
810 agg::image_filter_lut &filter)
811 {
812 switch (params.interpolation) {
813 case NEAREST:
814 case _n_interpolation:
815 // Never should get here. Here to silence compiler warnings.
816 break;
817
818 case HANNING:
819 filter.calculate(agg::image_filter_hanning(), params.norm);
820 break;
821
822 case HAMMING:
823 filter.calculate(agg::image_filter_hamming(), params.norm);
824 break;
825
826 case HERMITE:
827 filter.calculate(agg::image_filter_hermite(), params.norm);
828 break;
829
830 case BILINEAR:
831 filter.calculate(agg::image_filter_bilinear(), params.norm);
832 break;
833
834 case BICUBIC:
835 filter.calculate(agg::image_filter_bicubic(), params.norm);
836 break;
837
838 case SPLINE16:
839 filter.calculate(agg::image_filter_spline16(), params.norm);
840 break;
841
842 case SPLINE36:
843 filter.calculate(agg::image_filter_spline36(), params.norm);
844 break;
845
846 case KAISER:
847 filter.calculate(agg::image_filter_kaiser(), params.norm);
848 break;
849
850 case QUADRIC:
851 filter.calculate(agg::image_filter_quadric(), params.norm);
852 break;
853
854 case CATROM:
855 filter.calculate(agg::image_filter_catrom(), params.norm);
856 break;
857
858 case GAUSSIAN:
859 filter.calculate(agg::image_filter_gaussian(), params.norm);
860 break;
861
862 case BESSEL:
863 filter.calculate(agg::image_filter_bessel(), params.norm);
864 break;
865
866 case MITCHELL:
867 filter.calculate(agg::image_filter_mitchell(), params.norm);
868 break;
869
870 case SINC:
871 filter.calculate(agg::image_filter_sinc(params.radius), params.norm);
872 break;
873
874 case LANCZOS:
875 filter.calculate(agg::image_filter_lanczos(params.radius), params.norm);
876 break;
877
878 case BLACKMAN:
879 filter.calculate(agg::image_filter_blackman(params.radius), params.norm);
880 break;
881 }
882 }
883
884
885 template<class T>
resample(const T * input,int in_width,int in_height,T * output,int out_width,int out_height,resample_params_t & params)886 void resample(
887 const T *input, int in_width, int in_height,
888 T *output, int out_width, int out_height,
889 resample_params_t ¶ms)
890 {
891 typedef type_mapping<T> type_mapping_t;
892
893 typedef typename type_mapping_t::pixfmt_type input_pixfmt_t;
894 typedef typename type_mapping_t::pixfmt_type output_pixfmt_t;
895
896 typedef agg::renderer_base<output_pixfmt_t> renderer_t;
897 typedef agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl> rasterizer_t;
898
899 typedef agg::wrap_mode_reflect reflect_t;
900 typedef agg::image_accessor_wrap<input_pixfmt_t, reflect_t, reflect_t> image_accessor_t;
901
902 typedef agg::span_allocator<typename type_mapping_t::color_type> span_alloc_t;
903 typedef span_conv_alpha<typename type_mapping_t::color_type> span_conv_alpha_t;
904
905 typedef agg::span_interpolator_linear<> affine_interpolator_t;
906 typedef agg::span_interpolator_adaptor<agg::span_interpolator_linear<>, lookup_distortion>
907 arbitrary_interpolator_t;
908
909 if (params.interpolation != NEAREST &&
910 params.is_affine &&
911 fabs(params.affine.sx) == 1.0 &&
912 fabs(params.affine.sy) == 1.0 &&
913 params.affine.shx == 0.0 &&
914 params.affine.shy == 0.0) {
915 params.interpolation = NEAREST;
916 }
917
918 span_alloc_t span_alloc;
919 rasterizer_t rasterizer;
920 agg::scanline_u8 scanline;
921
922 span_conv_alpha_t conv_alpha(params.alpha);
923
924 agg::rendering_buffer input_buffer;
925 input_buffer.attach((unsigned char *)input, in_width, in_height,
926 in_width * sizeof(T));
927 input_pixfmt_t input_pixfmt(input_buffer);
928 image_accessor_t input_accessor(input_pixfmt);
929
930 agg::rendering_buffer output_buffer;
931 output_buffer.attach((unsigned char *)output, out_width, out_height,
932 out_width * sizeof(T));
933 output_pixfmt_t output_pixfmt(output_buffer);
934 renderer_t renderer(output_pixfmt);
935
936 agg::trans_affine inverted = params.affine;
937 inverted.invert();
938
939 rasterizer.clip_box(0, 0, out_width, out_height);
940
941 agg::path_storage path;
942 if (params.is_affine) {
943 path.move_to(0, 0);
944 path.line_to(in_width, 0);
945 path.line_to(in_width, in_height);
946 path.line_to(0, in_height);
947 path.close_polygon();
948 agg::conv_transform<agg::path_storage> rectangle(path, params.affine);
949 rasterizer.add_path(rectangle);
950 } else {
951 path.move_to(0, 0);
952 path.line_to(out_width, 0);
953 path.line_to(out_width, out_height);
954 path.line_to(0, out_height);
955 path.close_polygon();
956 rasterizer.add_path(path);
957 }
958
959 if (params.interpolation == NEAREST) {
960 if (params.is_affine) {
961 typedef typename type_mapping_t::template span_gen_nn_type<image_accessor_t, affine_interpolator_t>::type span_gen_t;
962 typedef agg::span_converter<span_gen_t, span_conv_alpha_t> span_conv_t;
963 typedef agg::renderer_scanline_aa<renderer_t, span_alloc_t, span_conv_t> nn_renderer_t;
964
965 affine_interpolator_t interpolator(inverted);
966 span_gen_t span_gen(input_accessor, interpolator);
967 span_conv_t span_conv(span_gen, conv_alpha);
968 nn_renderer_t nn_renderer(renderer, span_alloc, span_conv);
969 agg::render_scanlines(rasterizer, scanline, nn_renderer);
970 } else {
971 typedef typename type_mapping_t::template span_gen_nn_type<image_accessor_t, arbitrary_interpolator_t>::type span_gen_t;
972 typedef agg::span_converter<span_gen_t, span_conv_alpha_t> span_conv_t;
973 typedef agg::renderer_scanline_aa<renderer_t, span_alloc_t, span_conv_t> nn_renderer_t;
974
975 lookup_distortion dist(
976 params.transform_mesh, in_width, in_height, out_width, out_height);
977 arbitrary_interpolator_t interpolator(inverted, dist);
978 span_gen_t span_gen(input_accessor, interpolator);
979 span_conv_t span_conv(span_gen, conv_alpha);
980 nn_renderer_t nn_renderer(renderer, span_alloc, span_conv);
981 agg::render_scanlines(rasterizer, scanline, nn_renderer);
982 }
983 } else {
984 agg::image_filter_lut filter;
985 get_filter(params, filter);
986
987 if (params.is_affine && params.resample) {
988 typedef typename type_mapping_t::template span_gen_affine_type<image_accessor_t>::type span_gen_t;
989 typedef agg::span_converter<span_gen_t, span_conv_alpha_t> span_conv_t;
990 typedef agg::renderer_scanline_aa<renderer_t, span_alloc_t, span_conv_t> int_renderer_t;
991
992 affine_interpolator_t interpolator(inverted);
993 span_gen_t span_gen(input_accessor, interpolator, filter);
994 span_conv_t span_conv(span_gen, conv_alpha);
995 int_renderer_t int_renderer(renderer, span_alloc, span_conv);
996 agg::render_scanlines(rasterizer, scanline, int_renderer);
997 } else {
998 typedef typename type_mapping_t::template span_gen_filter_type<image_accessor_t, arbitrary_interpolator_t>::type span_gen_t;
999 typedef agg::span_converter<span_gen_t, span_conv_alpha_t> span_conv_t;
1000 typedef agg::renderer_scanline_aa<renderer_t, span_alloc_t, span_conv_t> int_renderer_t;
1001
1002 lookup_distortion dist(
1003 params.transform_mesh, in_width, in_height, out_width, out_height);
1004 arbitrary_interpolator_t interpolator(inverted, dist);
1005 span_gen_t span_gen(input_accessor, interpolator, filter);
1006 span_conv_t span_conv(span_gen, conv_alpha);
1007 int_renderer_t int_renderer(renderer, span_alloc, span_conv);
1008 agg::render_scanlines(rasterizer, scanline, int_renderer);
1009 }
1010 }
1011 }
1012
1013 #endif /* RESAMPLE_H */
1014