Anti-Grain Geometry Tutorial
agg_span_gradient_contour.h
1 //----------------------------------------------------------------------------
2 // AGG Contribution Pack - Gradients 1 (AGG CP - Gradients 1)
3 // http://milan.marusinec.sk/aggcp
4 //
5 // For Anti-Grain Geometry - Version 2.4
6 // http://www.antigrain.org
7 //
8 // Contribution Created By:
9 // Milan Marusinec alias Milano
10 // milan@marusinec.sk
11 // Copyright (c) 2007-2008
12 //
13 // Permission to copy, use, modify, sell and distribute this software
14 // is granted provided this copyright notice appears in all copies.
15 // This software is provided "as is" without express or implied
16 // warranty, and with no claim as to its suitability for any purpose.
17 //
18 // [History] -----------------------------------------------------------------
19 //
20 // 02.02.2008-Milano: Ported from Object Pascal code of AggPas
21 //
22 #ifndef AGG_SPAN_GRADIENT_CONTOUR_INCLUDED
23 #define AGG_SPAN_GRADIENT_CONTOUR_INCLUDED
24 
25 #include "agg_basics.h"
26 #include "agg_trans_affine.h"
27 #include "agg_path_storage.h"
28 #include "agg_pixfmt_gray.h"
29 #include "agg_conv_transform.h"
30 #include "agg_conv_curve.h"
31 #include "agg_bounding_rect.h"
32 #include "agg_renderer_base.h"
33 #include "agg_renderer_primitives.h"
34 #include "agg_rasterizer_outline.h"
35 #include "agg_span_gradient.h"
36 
37 #include <cfloat>
38 #include <cmath>
39 #include <cstring>
40 
41 namespace agg
42 {
43 
44  //==========================================================gradient_contour
46  {
47  private:
48  int8u* m_buffer;
49  int m_width;
50  int m_height;
51  int m_frame;
52 
53  double m_d1;
54  double m_d2;
55 
56  public:
58  m_buffer(NULL),
59  m_width(0),
60  m_height(0),
61  m_frame(10),
62  m_d1(0),
63  m_d2(100)
64  {
65  }
66 
67  gradient_contour(double d1, double d2) :
68  m_buffer(NULL),
69  m_width(0),
70  m_height(0),
71  m_frame(10),
72  m_d1(d1),
73  m_d2(d2)
74  {
75  }
76 
78  {
79  if (m_buffer)
80  {
81  delete [] m_buffer;
82  }
83  }
84 
85  int8u* contour_create(path_storage* ps );
86 
87  int contour_width() { return m_width; }
88  int contour_height() { return m_height; }
89 
90  void d1(double d ) { m_d1 = d; }
91  void d2(double d ) { m_d2 = d; }
92 
93  void frame(int f ) { m_frame = f; }
94  int frame() { return m_frame; }
95 
96  int calculate(int x, int y, int d) const
97  {
98  if (m_buffer)
99  {
100  int px = x >> agg::gradient_subpixel_shift;
101  int py = y >> agg::gradient_subpixel_shift;
102 
103  px %= m_width;
104 
105  if (px < 0)
106  {
107  px += m_width;
108  }
109 
110  py %= m_height;
111 
112  if (py < 0 )
113  {
114  py += m_height;
115  }
116 
117  return iround(m_buffer[py * m_width + px ] * (m_d2 / 256 ) + m_d1 ) << gradient_subpixel_shift;
118 
119  }
120  else
121  {
122  return 0;
123  }
124  }
125 
126  };
127 
128  static AGG_INLINE int square(int x ) { return x * x; }
129 
130  // DT algorithm by: Pedro Felzenszwalb
131  void dt(float* spanf, float* spang, float* spanr, int* spann ,int length )
132  {
133  int k = 0;
134  float s;
135 
136  spann[0 ] = 0;
137  spang[0 ] = -FLT_MAX;
138  spang[1 ] = FLT_MAX;
139 
140  for (int q = 1; q <= length - 1; q++)
141  {
142  s = ((spanf[q ] + square(q ) ) - (spanf[spann[k ] ] + square(spann[k ] ) ) ) / (2 * q - 2 * spann[k ] );
143 
144  while (s <= spang[k ])
145  {
146  k--;
147  s = ((spanf[q ] + square(q ) ) - (spanf[spann[k ] ] + square(spann[k ] ) ) ) / (2 * q - 2 * spann[k ] );
148  }
149 
150  k++;
151  spann[k ] = q;
152  spang[k ] = s;
153  spang[k + 1 ] = FLT_MAX;
154 
155  }
156 
157  k = 0;
158 
159  for (int q = 0; q <= length - 1; q++)
160  {
161  while (spang[k + 1 ] < q )
162  {
163  k++;
164  }
165 
166  spanr[q ] = square(q - spann[k ] ) + spanf[spann[k ] ];
167  }
168  }
169 
170  // DT algorithm by: Pedro Felzenszwalb
171  int8u* gradient_contour::contour_create(path_storage* ps )
172  {
173  int8u* result = NULL;
174 
175  if (ps)
176  {
177  // I. Render Black And White NonAA Stroke of the Path
178  // Path Bounding Box + Some Frame Space Around [configurable]
180 
181  double x1, y1, x2, y2;
182 
183  if (agg::bounding_rect_single(conv ,0 ,&x1 ,&y1 ,&x2 ,&y2 ))
184  {
185  // Create BW Rendering Surface
186  int width = int(ceil(x2 - x1 ) ) + m_frame * 2 + 1;
187  int height = int(ceil(y2 - y1 ) ) + m_frame * 2 + 1;
188 
189  int8u* buffer = new int8u[width * height];
190 
191  if (buffer)
192  {
193  std::memset(buffer ,255 ,width * height );
194 
195  // Setup VG Engine & Render
197  rb.attach(buffer ,width ,height ,width );
198 
199  agg::pixfmt_gray8 pf(rb);
201 
204 
205  agg::trans_affine mtx;
206  mtx *= agg::trans_affine_translation(-x1 + m_frame, -y1 + m_frame );
207 
209 
210  prim.line_color(agg::rgba8(0 ,0 ,0 ,255 ) );
211  ras.add_path(trans );
212 
213  // II. Distance Transform
214  // Create Float Buffer + 0 vs infinity assignment
215  float* image = new float[width * height];
216 
217  if (image)
218  {
219  for (int y = 0, l = 0; y < height; y++ )
220  {
221  for (int x = 0; x < width; x++, l++ )
222  {
223  if (buffer[l ] == 0)
224  {
225  image[l ] = 0.0;
226  }
227  else
228  {
229  image[l ] = FLT_MAX;
230  }
231  }
232 
233  }
234 
235  // DT of 2d
236  // SubBuff<float> max width,height
237  int length = width;
238 
239  if (height > length)
240  {
241  length = height;
242  }
243 
244  float* spanf = new float[length];
245  float* spang = new float[length + 1];
246  float* spanr = new float[length];
247  int* spann = new int[length];
248 
249  if ((spanf) && (spang) && (spanr) && (spann))
250  {
251  // Transform along columns
252  for (int x = 0; x < width; x++ )
253  {
254  for (int y = 0; y < height; y++ )
255  {
256  spanf[y] = image[y * width + x];
257  }
258 
259  // DT of 1d
260  dt(spanf ,spang ,spanr ,spann ,height );
261 
262  for (int y = 0; y < height; y++ )
263  {
264  image[y * width + x] = spanr[y];
265  }
266  }
267 
268  // Transform along rows
269  for (int y = 0; y < height; y++ )
270  {
271  for (int x = 0; x < width; x++ )
272  {
273  spanf[x] = image[y * width + x];
274  }
275 
276  // DT of 1d
277  dt(spanf ,spang ,spanr ,spann ,width );
278 
279  for (int x = 0; x < width; x++ )
280  {
281  image[y * width + x] = spanr[x];
282  }
283  }
284 
285  // Take Square Roots, Min & Max
286  float min = std::sqrt(image[0] );
287  float max = min;
288 
289  for (int y = 0, l = 0; y < height; y++ )
290  {
291  for (int x = 0; x < width; x++, l++ )
292  {
293  image[l] = std::sqrt(image[l]);
294 
295  if (min > image[l])
296  {
297  min = image[l];
298  }
299 
300  if (max < image[l])
301  {
302  max = image[l];
303  }
304 
305  }
306  }
307 
308  // III. Convert To Grayscale
309  if (min == max)
310  {
311  std::memset(buffer ,0 ,width * height );
312  }
313  else
314  {
315  float scale = 255 / (max - min );
316 
317  for (int y = 0, l = 0; y < height; y++ )
318  {
319  for (int x = 0; x < width; x++ ,l++ )
320  {
321  buffer[l] = int8u(int((image[l] - min ) * scale ));
322  }
323  }
324  }
325 
326  // OK
327  if (m_buffer)
328  {
329  delete [] m_buffer;
330  }
331 
332  m_buffer = buffer;
333  m_width = width;
334  m_height = height;
335 
336  buffer = NULL;
337  result = m_buffer;
338 
339  }
340 
341  if (spanf) { delete [] spanf; }
342  if (spang) { delete [] spang; }
343  if (spanr) { delete [] spanr; }
344  if (spann) { delete [] spann; }
345 
346  delete [] image;
347 
348  }
349  }
350 
351  if (buffer)
352  {
353  delete [] buffer;
354  }
355 
356  }
357 
358  }
359  return result;
360  }
361 
362 }
363 
364 #endif
Definition: agg_arc.cpp:24