1//----------------------------------------------------------------------------
2// Anti-Grain Geometry - Version 2.4
3// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4//
5// Permission to copy, use, modify, sell and distribute this software
6// is granted provided this copyright notice appears in all copies.
7// This software is provided "as is" without express or implied
8// warranty, and with no claim as to its suitability for any purpose.
9//
10//----------------------------------------------------------------------------
11// Contact: mcseem@antigrain.com
12//          mcseemagg@yahoo.com
13//          http://www.antigrain.com
14//----------------------------------------------------------------------------
15//
16// Image transformations with filtering. Span generator base class
17//
18//----------------------------------------------------------------------------
19#ifndef AGG_SPAN_IMAGE_FILTER_INCLUDED
20#define AGG_SPAN_IMAGE_FILTER_INCLUDED
21
22#include "agg_basics.h"
23#include "agg_image_filters.h"
24#include "agg_span_interpolator_linear.h"
25
26namespace agg
27{
28
29    //-------------------------------------------------------span_image_filter
30    template<class Source, class Interpolator> class span_image_filter
31    {
32    public:
33        typedef Source source_type;
34        typedef Interpolator interpolator_type;
35
36        //--------------------------------------------------------------------
37        span_image_filter() {}
38        span_image_filter(source_type& src,
39                          interpolator_type& interpolator,
40                          const image_filter_lut* filter) :
41            m_src(&src),
42            m_interpolator(&interpolator),
43            m_filter(filter),
44            m_dx_dbl(0.5),
45            m_dy_dbl(0.5),
46            m_dx_int(image_subpixel_scale / 2),
47            m_dy_int(image_subpixel_scale / 2)
48        {}
49        void attach(source_type& v) { m_src = &v; }
50
51        //--------------------------------------------------------------------
52               source_type& source()            { return *m_src; }
53        const  source_type& source()      const { return *m_src; }
54        const  image_filter_lut& filter() const { return *m_filter; }
55        int    filter_dx_int()            const { return m_dx_int; }
56        int    filter_dy_int()            const { return m_dy_int; }
57        double filter_dx_dbl()            const { return m_dx_dbl; }
58        double filter_dy_dbl()            const { return m_dy_dbl; }
59
60        //--------------------------------------------------------------------
61        void interpolator(interpolator_type& v)  { m_interpolator = &v; }
62        void filter(const image_filter_lut& v)   { m_filter = &v; }
63        void filter_offset(double dx, double dy)
64        {
65            m_dx_dbl = dx;
66            m_dy_dbl = dy;
67            m_dx_int = iround(dx * image_subpixel_scale);
68            m_dy_int = iround(dy * image_subpixel_scale);
69        }
70        void filter_offset(double d) { filter_offset(d, d); }
71
72        //--------------------------------------------------------------------
73        interpolator_type& interpolator() { return *m_interpolator; }
74
75        //--------------------------------------------------------------------
76        void prepare() {}
77
78        //--------------------------------------------------------------------
79    private:
80        source_type*            m_src;
81        interpolator_type*      m_interpolator;
82        const image_filter_lut* m_filter;
83        double   m_dx_dbl;
84        double   m_dy_dbl;
85        unsigned m_dx_int;
86        unsigned m_dy_int;
87    };
88
89
90
91
92    //==============================================span_image_resample_affine
93    template<class Source>
94    class span_image_resample_affine :
95    public span_image_filter<Source, span_interpolator_linear<trans_affine> >
96    {
97    public:
98        typedef Source source_type;
99        typedef span_interpolator_linear<trans_affine> interpolator_type;
100        typedef span_image_filter<source_type, interpolator_type> base_type;
101
102        //--------------------------------------------------------------------
103        span_image_resample_affine() :
104            m_scale_limit(200.0),
105            m_blur_x(1.0),
106            m_blur_y(1.0)
107        {}
108
109        //--------------------------------------------------------------------
110        span_image_resample_affine(source_type& src,
111                                   interpolator_type& inter,
112                                   const image_filter_lut& filter) :
113            base_type(src, inter, &filter),
114            m_scale_limit(200.0),
115            m_blur_x(1.0),
116            m_blur_y(1.0)
117        {}
118
119
120        //--------------------------------------------------------------------
121        int  scale_limit() const { return uround(m_scale_limit); }
122        void scale_limit(int v)  { m_scale_limit = v; }
123
124        //--------------------------------------------------------------------
125        double blur_x() const { return m_blur_x; }
126        double blur_y() const { return m_blur_y; }
127        void blur_x(double v) { m_blur_x = v; }
128        void blur_y(double v) { m_blur_y = v; }
129        void blur(double v) { m_blur_x = m_blur_y = v; }
130
131        //--------------------------------------------------------------------
132        void prepare()
133        {
134            double scale_x;
135            double scale_y;
136
137            base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y);
138
139            if(scale_x * scale_y > m_scale_limit)
140            {
141                scale_x = scale_x * m_scale_limit / (scale_x * scale_y);
142                scale_y = scale_y * m_scale_limit / (scale_x * scale_y);
143            }
144
145            if(scale_x < 1) scale_x = 1;
146            if(scale_y < 1) scale_y = 1;
147
148            if(scale_x > m_scale_limit) scale_x = m_scale_limit;
149            if(scale_y > m_scale_limit) scale_y = m_scale_limit;
150
151            scale_x *= m_blur_x;
152            scale_y *= m_blur_y;
153
154            if(scale_x < 1) scale_x = 1;
155            if(scale_y < 1) scale_y = 1;
156
157            m_rx     = uround(    scale_x * double(image_subpixel_scale));
158            m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale));
159
160            m_ry     = uround(    scale_y * double(image_subpixel_scale));
161            m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale));
162        }
163
164    protected:
165        int m_rx;
166        int m_ry;
167        int m_rx_inv;
168        int m_ry_inv;
169
170    private:
171        double m_scale_limit;
172        double m_blur_x;
173        double m_blur_y;
174    };
175
176
177
178    //=====================================================span_image_resample
179    template<class Source, class Interpolator>
180    class span_image_resample :
181    public span_image_filter<Source, Interpolator>
182    {
183    public:
184        typedef Source source_type;
185        typedef Interpolator interpolator_type;
186        typedef span_image_filter<source_type, interpolator_type> base_type;
187
188        //--------------------------------------------------------------------
189        span_image_resample() :
190            m_scale_limit(20),
191            m_blur_x(image_subpixel_scale),
192            m_blur_y(image_subpixel_scale)
193        {}
194
195        //--------------------------------------------------------------------
196        span_image_resample(source_type& src,
197                            interpolator_type& inter,
198                            const image_filter_lut& filter) :
199            base_type(src, inter, &filter),
200            m_scale_limit(20),
201            m_blur_x(image_subpixel_scale),
202            m_blur_y(image_subpixel_scale)
203        {}
204
205        //--------------------------------------------------------------------
206        int  scale_limit() const { return m_scale_limit; }
207        void scale_limit(int v)  { m_scale_limit = v; }
208
209        //--------------------------------------------------------------------
210        double blur_x() const { return double(m_blur_x) / double(image_subpixel_scale); }
211        double blur_y() const { return double(m_blur_y) / double(image_subpixel_scale); }
212        void blur_x(double v) { m_blur_x = uround(v * double(image_subpixel_scale)); }
213        void blur_y(double v) { m_blur_y = uround(v * double(image_subpixel_scale)); }
214        void blur(double v)   { m_blur_x =
215                                m_blur_y = uround(v * double(image_subpixel_scale)); }
216
217    protected:
218        AGG_INLINE void adjust_scale(int* rx, int* ry)
219        {
220            if(*rx < image_subpixel_scale) *rx = image_subpixel_scale;
221            if(*ry < image_subpixel_scale) *ry = image_subpixel_scale;
222            if(*rx > image_subpixel_scale * m_scale_limit)
223            {
224                *rx = image_subpixel_scale * m_scale_limit;
225            }
226            if(*ry > image_subpixel_scale * m_scale_limit)
227            {
228                *ry = image_subpixel_scale * m_scale_limit;
229            }
230            *rx = (*rx * m_blur_x) >> image_subpixel_shift;
231            *ry = (*ry * m_blur_y) >> image_subpixel_shift;
232            if(*rx < image_subpixel_scale) *rx = image_subpixel_scale;
233            if(*ry < image_subpixel_scale) *ry = image_subpixel_scale;
234        }
235
236        int m_scale_limit;
237        int m_blur_x;
238        int m_blur_y;
239    };
240
241
242
243
244}
245
246#endif
247