1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
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.
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
16 #ifndef AGG_SPAN_IMAGE_RESAMPLE_GRAY_INCLUDED
17 #define AGG_SPAN_IMAGE_RESAMPLE_GRAY_INCLUDED
19 #include "agg_color_gray.h"
20 #include "agg_span_image_resample.h"
25 //========================================span_image_resample_gray_affine
26 template<class ColorT
,
27 class Allocator
= span_allocator
<ColorT
> >
28 class span_image_resample_gray_affine
:
29 public span_image_resample_affine
<ColorT
, Allocator
>
32 typedef ColorT color_type
;
33 typedef Allocator alloc_type
;
34 typedef span_image_resample_affine
<color_type
, alloc_type
> base_type
;
35 typedef typename
base_type::interpolator_type interpolator_type
;
36 typedef typename
color_type::value_type value_type
;
37 typedef typename
color_type::long_type long_type
;
40 base_shift
= color_type::base_shift
,
41 base_mask
= color_type::base_mask
,
42 downscale_shift
= image_filter_shift
45 //--------------------------------------------------------------------
46 span_image_resample_gray_affine(alloc_type
& alloc
) : base_type(alloc
) {}
48 //--------------------------------------------------------------------
49 span_image_resample_gray_affine(alloc_type
& alloc
,
50 const rendering_buffer
& src
,
51 const color_type
& back_color
,
52 interpolator_type
& inter
,
53 const image_filter_lut
& filter
) :
54 base_type(alloc
, src
, back_color
, inter
, filter
)
58 //--------------------------------------------------------------------
59 color_type
* generate(int x
, int y
, unsigned len
)
61 base_type::interpolator().begin(x
+ base_type::filter_dx_dbl(),
62 y
+ base_type::filter_dy_dbl(), len
);
66 value_type back_v
= base_type::background_color().v
;
67 value_type back_a
= base_type::background_color().a
;
69 color_type
* span
= base_type::allocator().span();
71 int diameter
= base_type::filter().diameter();
72 int filter_size
= diameter
<< image_subpixel_shift
;
73 int radius_x
= (diameter
* base_type::m_rx
) >> 1;
74 int radius_y
= (diameter
* base_type::m_ry
) >> 1;
75 int maxx
= base_type::source_image().width() - 1;
76 int maxy
= base_type::source_image().height() - 1;
78 const int16
* weight_array
= base_type::filter().weight_array();
82 base_type::interpolator().coordinates(&x
, &y
);
84 x
+= base_type::filter_dx_int() - radius_x
;
85 y
+= base_type::filter_dy_int() - radius_y
;
87 fg
= src_alpha
= image_filter_size
/ 2;
89 int y_lr
= y
>> image_subpixel_shift
;
90 int y_hr
= ((image_subpixel_mask
- (y
& image_subpixel_mask
)) *
91 base_type::m_ry_inv
) >>
94 int x_lr_ini
= x
>> image_subpixel_shift
;
95 int x_hr_ini
= ((image_subpixel_mask
- (x
& image_subpixel_mask
)) *
96 base_type::m_rx_inv
) >>
100 int weight_y
= weight_array
[y_hr
];
103 if(y_lr
>= 0 && y_lr
<= maxy
)
105 const value_type
* fg_ptr
= (const value_type
*)
106 base_type::source_image().row(y_lr
) + x_lr
;
109 int weight
= (weight_y
* weight_array
[x_hr
] +
110 image_filter_size
/ 2) >>
113 if(x_lr
>= 0 && x_lr
<= maxx
)
115 fg
+= *fg_ptr
* weight
;
116 src_alpha
+= base_mask
* weight
;
120 fg
+= back_v
* weight
;
121 src_alpha
+= back_a
* weight
;
123 total_weight
+= weight
;
124 x_hr
+= base_type::m_rx_inv
;
128 while(x_hr
< filter_size
);
134 int weight
= (weight_y
* weight_array
[x_hr
] +
135 image_filter_size
/ 2) >>
138 total_weight
+= weight
;
139 fg
+= back_v
* weight
;
140 src_alpha
+= back_a
* weight
;
141 x_hr
+= base_type::m_rx_inv
;
143 while(x_hr
< filter_size
);
145 y_hr
+= base_type::m_ry_inv
;
148 while(y_hr
< filter_size
);
151 src_alpha
/= total_weight
;
154 if(src_alpha
< 0) src_alpha
= 0;
156 if(src_alpha
> base_mask
) src_alpha
= base_mask
;
157 if(fg
> src_alpha
) fg
= src_alpha
;
159 span
->v
= (value_type
)fg
;
160 span
->a
= (value_type
)src_alpha
;
163 ++base_type::interpolator();
165 return base_type::allocator().span();
175 //==============================================span_image_resample_gray
176 template<class ColorT
,
178 class Allocator
= span_allocator
<ColorT
> >
179 class span_image_resample_gray
:
180 public span_image_resample
<ColorT
, Interpolator
, Allocator
>
183 typedef ColorT color_type
;
184 typedef Interpolator interpolator_type
;
185 typedef Allocator alloc_type
;
186 typedef span_image_resample
<color_type
, interpolator_type
, alloc_type
> base_type
;
187 typedef typename
color_type::value_type value_type
;
188 typedef typename
color_type::long_type long_type
;
191 base_shift
= color_type::base_shift
,
192 base_mask
= color_type::base_mask
,
193 downscale_shift
= image_filter_shift
196 //--------------------------------------------------------------------
197 span_image_resample_gray(alloc_type
& alloc
) :
201 //--------------------------------------------------------------------
202 span_image_resample_gray(alloc_type
& alloc
,
203 const rendering_buffer
& src
,
204 const color_type
& back_color
,
205 interpolator_type
& inter
,
206 const image_filter_lut
& filter
) :
207 base_type(alloc
, src
, back_color
, inter
, filter
)
210 //--------------------------------------------------------------------
211 color_type
* generate(int x
, int y
, unsigned len
)
213 color_type
* span
= base_type::allocator().span();
214 base_type::interpolator().begin(x
+ base_type::filter_dx_dbl(),
215 y
+ base_type::filter_dy_dbl(), len
);
218 value_type back_v
= base_type::background_color().v
;
219 value_type back_a
= base_type::background_color().a
;
221 int diameter
= base_type::filter().diameter();
222 int filter_size
= diameter
<< image_subpixel_shift
;
224 const int16
* weight_array
= base_type::filter().weight_array();
230 int rx_inv
= image_subpixel_size
;
231 int ry_inv
= image_subpixel_size
;
232 base_type::interpolator().coordinates(&x
, &y
);
233 base_type::interpolator().local_scale(&rx
, &ry
);
235 rx
= (rx
* base_type::m_blur_x
) >> image_subpixel_shift
;
236 ry
= (ry
* base_type::m_blur_y
) >> image_subpixel_shift
;
238 if(rx
< image_subpixel_size
)
240 rx
= image_subpixel_size
;
244 if(rx
> image_subpixel_size
* base_type::m_scale_limit
)
246 rx
= image_subpixel_size
* base_type::m_scale_limit
;
248 rx_inv
= image_subpixel_size
* image_subpixel_size
/ rx
;
251 if(ry
< image_subpixel_size
)
253 ry
= image_subpixel_size
;
257 if(ry
> image_subpixel_size
* base_type::m_scale_limit
)
259 ry
= image_subpixel_size
* base_type::m_scale_limit
;
261 ry_inv
= image_subpixel_size
* image_subpixel_size
/ ry
;
264 int radius_x
= (diameter
* rx
) >> 1;
265 int radius_y
= (diameter
* ry
) >> 1;
266 int maxx
= base_type::source_image().width() - 1;
267 int maxy
= base_type::source_image().height() - 1;
269 x
+= base_type::filter_dx_int() - radius_x
;
270 y
+= base_type::filter_dy_int() - radius_y
;
272 fg
= src_alpha
= image_filter_size
/ 2;
274 int y_lr
= y
>> image_subpixel_shift
;
275 int y_hr
= ((image_subpixel_mask
- (y
& image_subpixel_mask
)) *
277 image_subpixel_shift
;
278 int total_weight
= 0;
279 int x_lr_ini
= x
>> image_subpixel_shift
;
280 int x_hr_ini
= ((image_subpixel_mask
- (x
& image_subpixel_mask
)) *
282 image_subpixel_shift
;
286 int weight_y
= weight_array
[y_hr
];
289 if(y_lr
>= 0 && y_lr
<= maxy
)
291 const value_type
* fg_ptr
= (const value_type
*)
292 base_type::source_image().row(y_lr
) + x_lr
;
295 int weight
= (weight_y
* weight_array
[x_hr
] +
296 image_filter_size
/ 2) >>
299 if(x_lr
>= 0 && x_lr
<= maxx
)
301 fg
+= *fg_ptr
* weight
;
302 src_alpha
+= base_mask
* weight
;
306 fg
+= back_v
* weight
;
307 src_alpha
+= back_a
* weight
;
309 total_weight
+= weight
;
314 while(x_hr
< filter_size
);
320 int weight
= (weight_y
* weight_array
[x_hr
] +
321 image_filter_size
/ 2) >>
324 total_weight
+= weight
;
325 fg
+= back_v
* weight
;
326 src_alpha
+= back_a
* weight
;
329 while(x_hr
< filter_size
);
334 while(y_hr
< filter_size
);
337 src_alpha
/= total_weight
;
340 if(src_alpha
< 0) src_alpha
= 0;
342 if(src_alpha
> base_mask
) src_alpha
= base_mask
;
343 if(fg
> src_alpha
) fg
= src_alpha
;
345 span
->v
= (value_type
)fg
;
346 span
->a
= (value_type
)src_alpha
;
349 ++base_type::interpolator();
351 return base_type::allocator().span();