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_RGBA_INCLUDED
17 #define AGG_SPAN_IMAGE_RESAMPLE_RGBA_INCLUDED
19 #include "agg_color_rgba.h"
20 #include "agg_span_image_resample.h"
25 //========================================span_image_resample_rgba_affine
26 template<class ColorT
,
28 class Allocator
= span_allocator
<ColorT
> >
29 class span_image_resample_rgba_affine
:
30 public span_image_resample_affine
<ColorT
, Allocator
>
33 typedef ColorT color_type
;
34 typedef Order order_type
;
35 typedef Allocator alloc_type
;
36 typedef span_image_resample_affine
<color_type
, alloc_type
> base_type
;
37 typedef typename
base_type::interpolator_type interpolator_type
;
38 typedef typename
color_type::value_type value_type
;
39 typedef typename
color_type::long_type long_type
;
42 base_shift
= color_type::base_shift
,
43 base_mask
= color_type::base_mask
,
44 downscale_shift
= image_filter_shift
47 //--------------------------------------------------------------------
48 span_image_resample_rgba_affine(alloc_type
& alloc
) : base_type(alloc
) {}
50 //--------------------------------------------------------------------
51 span_image_resample_rgba_affine(alloc_type
& alloc
,
52 const rendering_buffer
& src
,
53 const color_type
& back_color
,
54 interpolator_type
& inter
,
55 const image_filter_lut
& filter
) :
56 base_type(alloc
, src
, back_color
, inter
, filter
)
60 //--------------------------------------------------------------------
61 color_type
* generate(int x
, int y
, unsigned len
)
63 base_type::interpolator().begin(x
+ base_type::filter_dx_dbl(),
64 y
+ base_type::filter_dy_dbl(), len
);
67 value_type back_r
= base_type::background_color().r
;
68 value_type back_g
= base_type::background_color().g
;
69 value_type back_b
= base_type::background_color().b
;
70 value_type back_a
= base_type::background_color().a
;
72 color_type
* span
= base_type::allocator().span();
74 int diameter
= base_type::filter().diameter();
75 int filter_size
= diameter
<< image_subpixel_shift
;
76 int radius_x
= (diameter
* base_type::m_rx
) >> 1;
77 int radius_y
= (diameter
* base_type::m_ry
) >> 1;
78 int maxx
= base_type::source_image().width() - 1;
79 int maxy
= base_type::source_image().height() - 1;
81 const int16
* weight_array
= base_type::filter().weight_array();
85 base_type::interpolator().coordinates(&x
, &y
);
87 x
+= base_type::filter_dx_int() - radius_x
;
88 y
+= base_type::filter_dy_int() - radius_y
;
90 fg
[0] = fg
[1] = fg
[2] = fg
[3] = image_filter_size
/ 2;
92 int y_lr
= y
>> image_subpixel_shift
;
93 int y_hr
= ((image_subpixel_mask
- (y
& image_subpixel_mask
)) *
94 base_type::m_ry_inv
) >>
97 int x_lr_ini
= x
>> image_subpixel_shift
;
98 int x_hr_ini
= ((image_subpixel_mask
- (x
& image_subpixel_mask
)) *
99 base_type::m_rx_inv
) >>
100 image_subpixel_shift
;
103 int weight_y
= weight_array
[y_hr
];
106 if(y_lr
>= 0 && y_lr
<= maxy
)
108 const value_type
* fg_ptr
= (const value_type
*)
109 base_type::source_image().row(y_lr
) + (x_lr
<< 2);
112 int weight
= (weight_y
* weight_array
[x_hr
] +
113 image_filter_size
/ 2) >>
116 if(x_lr
>= 0 && x_lr
<= maxx
)
118 fg
[0] += fg_ptr
[0] * weight
;
119 fg
[1] += fg_ptr
[1] * weight
;
120 fg
[2] += fg_ptr
[2] * weight
;
121 fg
[3] += fg_ptr
[3] * weight
;
125 fg
[order_type::R
] += back_r
* weight
;
126 fg
[order_type::G
] += back_g
* weight
;
127 fg
[order_type::B
] += back_b
* weight
;
128 fg
[order_type::A
] += back_a
* weight
;
130 total_weight
+= weight
;
132 x_hr
+= base_type::m_rx_inv
;
135 while(x_hr
< filter_size
);
141 int weight
= (weight_y
* weight_array
[x_hr
] +
142 image_filter_size
/ 2) >>
145 total_weight
+= weight
;
146 fg
[order_type::R
] += back_r
* weight
;
147 fg
[order_type::G
] += back_g
* weight
;
148 fg
[order_type::B
] += back_b
* weight
;
149 fg
[order_type::A
] += back_a
* weight
;
150 x_hr
+= base_type::m_rx_inv
;
152 while(x_hr
< filter_size
);
154 y_hr
+= base_type::m_ry_inv
;
157 while(y_hr
< filter_size
);
159 fg
[0] /= total_weight
;
160 fg
[1] /= total_weight
;
161 fg
[2] /= total_weight
;
162 fg
[3] /= total_weight
;
164 if(fg
[0] < 0) fg
[0] = 0;
165 if(fg
[1] < 0) fg
[1] = 0;
166 if(fg
[2] < 0) fg
[2] = 0;
167 if(fg
[3] < 0) fg
[3] = 0;
169 if(fg
[order_type::A
] > base_mask
) fg
[order_type::A
] = base_mask
;
170 if(fg
[order_type::R
] > fg
[order_type::A
]) fg
[order_type::R
] = fg
[order_type::A
];
171 if(fg
[order_type::G
] > fg
[order_type::A
]) fg
[order_type::G
] = fg
[order_type::A
];
172 if(fg
[order_type::B
] > fg
[order_type::A
]) fg
[order_type::B
] = fg
[order_type::A
];
174 span
->r
= (value_type
)fg
[order_type::R
];
175 span
->g
= (value_type
)fg
[order_type::G
];
176 span
->b
= (value_type
)fg
[order_type::B
];
177 span
->a
= (value_type
)fg
[order_type::A
];
180 ++base_type::interpolator();
182 return base_type::allocator().span();
192 //==============================================span_image_resample_rgba
193 template<class ColorT
,
196 class Allocator
= span_allocator
<ColorT
> >
197 class span_image_resample_rgba
:
198 public span_image_resample
<ColorT
, Interpolator
, Allocator
>
201 typedef ColorT color_type
;
202 typedef Order order_type
;
203 typedef Interpolator interpolator_type
;
204 typedef Allocator alloc_type
;
205 typedef span_image_resample
<color_type
, interpolator_type
, alloc_type
> base_type
;
206 typedef typename
color_type::value_type value_type
;
207 typedef typename
color_type::long_type long_type
;
210 base_shift
= color_type::base_shift
,
211 base_mask
= color_type::base_mask
,
212 downscale_shift
= image_filter_shift
215 //--------------------------------------------------------------------
216 span_image_resample_rgba(alloc_type
& alloc
) :
220 //--------------------------------------------------------------------
221 span_image_resample_rgba(alloc_type
& alloc
,
222 const rendering_buffer
& src
,
223 const color_type
& back_color
,
224 interpolator_type
& inter
,
225 const image_filter_lut
& filter
) :
226 base_type(alloc
, src
, back_color
, inter
, filter
)
229 //--------------------------------------------------------------------
230 color_type
* generate(int x
, int y
, unsigned len
)
232 color_type
* span
= base_type::allocator().span();
233 base_type::interpolator().begin(x
+ base_type::filter_dx_dbl(),
234 y
+ base_type::filter_dy_dbl(), len
);
236 value_type back_r
= base_type::background_color().r
;
237 value_type back_g
= base_type::background_color().g
;
238 value_type back_b
= base_type::background_color().b
;
239 value_type back_a
= base_type::background_color().a
;
241 int diameter
= base_type::filter().diameter();
242 int filter_size
= diameter
<< image_subpixel_shift
;
244 const int16
* weight_array
= base_type::filter().weight_array();
250 int rx_inv
= image_subpixel_size
;
251 int ry_inv
= image_subpixel_size
;
252 base_type::interpolator().coordinates(&x
, &y
);
253 base_type::interpolator().local_scale(&rx
, &ry
);
255 rx
= (rx
* base_type::m_blur_x
) >> image_subpixel_shift
;
256 ry
= (ry
* base_type::m_blur_y
) >> image_subpixel_shift
;
258 if(rx
< image_subpixel_size
)
260 rx
= image_subpixel_size
;
264 if(rx
> image_subpixel_size
* base_type::m_scale_limit
)
266 rx
= image_subpixel_size
* base_type::m_scale_limit
;
268 rx_inv
= image_subpixel_size
* image_subpixel_size
/ rx
;
271 if(ry
< image_subpixel_size
)
273 ry
= image_subpixel_size
;
277 if(ry
> image_subpixel_size
* base_type::m_scale_limit
)
279 ry
= image_subpixel_size
* base_type::m_scale_limit
;
281 ry_inv
= image_subpixel_size
* image_subpixel_size
/ ry
;
284 int radius_x
= (diameter
* rx
) >> 1;
285 int radius_y
= (diameter
* ry
) >> 1;
286 int maxx
= base_type::source_image().width() - 1;
287 int maxy
= base_type::source_image().height() - 1;
289 x
+= base_type::filter_dx_int() - radius_x
;
290 y
+= base_type::filter_dy_int() - radius_y
;
292 fg
[0] = fg
[1] = fg
[2] = fg
[3] = image_filter_size
/ 2;
294 int y_lr
= y
>> image_subpixel_shift
;
295 int y_hr
= ((image_subpixel_mask
- (y
& image_subpixel_mask
)) *
297 image_subpixel_shift
;
298 int total_weight
= 0;
299 int x_lr_ini
= x
>> image_subpixel_shift
;
300 int x_hr_ini
= ((image_subpixel_mask
- (x
& image_subpixel_mask
)) *
302 image_subpixel_shift
;
306 int weight_y
= weight_array
[y_hr
];
309 if(y_lr
>= 0 && y_lr
<= maxy
)
311 const value_type
* fg_ptr
= (const value_type
*)
312 base_type::source_image().row(y_lr
) + (x_lr
<< 2);
315 int weight
= (weight_y
* weight_array
[x_hr
] +
316 image_filter_size
/ 2) >>
319 if(x_lr
>= 0 && x_lr
<= maxx
)
321 fg
[0] += fg_ptr
[0] * weight
;
322 fg
[1] += fg_ptr
[1] * weight
;
323 fg
[2] += fg_ptr
[2] * weight
;
324 fg
[3] += fg_ptr
[3] * weight
;
328 fg
[order_type::R
] += back_r
* weight
;
329 fg
[order_type::G
] += back_g
* weight
;
330 fg
[order_type::B
] += back_b
* weight
;
331 fg
[order_type::A
] += back_a
* weight
;
333 total_weight
+= weight
;
338 while(x_hr
< filter_size
);
344 int weight
= (weight_y
* weight_array
[x_hr
] +
345 image_filter_size
/ 2) >>
348 total_weight
+= weight
;
349 fg
[order_type::R
] += back_r
* weight
;
350 fg
[order_type::G
] += back_g
* weight
;
351 fg
[order_type::B
] += back_b
* weight
;
352 fg
[order_type::A
] += back_a
* weight
;
355 while(x_hr
< filter_size
);
360 while(y_hr
< filter_size
);
362 fg
[0] /= total_weight
;
363 fg
[1] /= total_weight
;
364 fg
[2] /= total_weight
;
365 fg
[3] /= total_weight
;
367 if(fg
[0] < 0) fg
[0] = 0;
368 if(fg
[1] < 0) fg
[1] = 0;
369 if(fg
[2] < 0) fg
[2] = 0;
370 if(fg
[3] < 0) fg
[3] = 0;
372 if(fg
[order_type::A
] > base_mask
) fg
[order_type::A
] = base_mask
;
373 if(fg
[order_type::R
] > fg
[order_type::R
]) fg
[order_type::R
] = fg
[order_type::R
];
374 if(fg
[order_type::G
] > fg
[order_type::G
]) fg
[order_type::G
] = fg
[order_type::G
];
375 if(fg
[order_type::B
] > fg
[order_type::B
]) fg
[order_type::B
] = fg
[order_type::B
];
377 span
->r
= (value_type
)fg
[order_type::R
];
378 span
->g
= (value_type
)fg
[order_type::G
];
379 span
->b
= (value_type
)fg
[order_type::B
];
380 span
->a
= (value_type
)fg
[order_type::A
];
383 ++base_type::interpolator();
385 return base_type::allocator().span();