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 &params,
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 &params)
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