update dev300-m57
[ooovba.git] / agg / inc / agg_span_image_resample_rgba.h
blobb1e02dda87d04345367b842f2488dbf5c28e6cae
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
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 //----------------------------------------------------------------------------
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"
22 namespace agg
25 //========================================span_image_resample_rgba_affine
26 template<class ColorT,
27 class Order,
28 class Allocator = span_allocator<ColorT> >
29 class span_image_resample_rgba_affine :
30 public span_image_resample_affine<ColorT, Allocator>
32 public:
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;
40 enum
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);
66 long_type fg[4];
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) >>
95 image_subpixel_shift;
96 int total_weight = 0;
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];
104 int x_lr = x_lr_ini;
105 int x_hr = x_hr_ini;
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) >>
114 downscale_shift;
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;
123 else
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;
131 fg_ptr += 4;
132 x_hr += base_type::m_rx_inv;
133 ++x_lr;
135 while(x_hr < filter_size);
137 else
141 int weight = (weight_y * weight_array[x_hr] +
142 image_filter_size / 2) >>
143 downscale_shift;
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;
155 ++y_lr;
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];
179 ++span;
180 ++base_type::interpolator();
181 } while(--len);
182 return base_type::allocator().span();
192 //==============================================span_image_resample_rgba
193 template<class ColorT,
194 class Order,
195 class Interpolator,
196 class Allocator = span_allocator<ColorT> >
197 class span_image_resample_rgba :
198 public span_image_resample<ColorT, Interpolator, Allocator>
200 public:
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;
208 enum
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) :
217 base_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);
235 long_type fg[4];
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();
248 int rx;
249 int ry;
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;
262 else
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;
275 else
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)) *
296 ry_inv) >>
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)) *
301 rx_inv) >>
302 image_subpixel_shift;
306 int weight_y = weight_array[y_hr];
307 int x_lr = x_lr_ini;
308 int x_hr = x_hr_ini;
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) >>
317 downscale_shift;
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;
326 else
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;
334 fg_ptr += 4;
335 x_hr += rx_inv;
336 ++x_lr;
338 while(x_hr < filter_size);
340 else
344 int weight = (weight_y * weight_array[x_hr] +
345 image_filter_size / 2) >>
346 downscale_shift;
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;
353 x_hr += rx_inv;
355 while(x_hr < filter_size);
357 y_hr += ry_inv;
358 ++y_lr;
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];
382 ++span;
383 ++base_type::interpolator();
384 } while(--len);
385 return base_type::allocator().span();
393 #endif