Fawkes API  Fawkes Development Version
mono_drawer.cpp
1 
2 /***************************************************************************
3  * mono_drawer.cpp - Utility to draw in a buffer
4  *
5  * Generated: Wed Feb 08 20:55:38 2006
6  * Copyright 2005-2007 Tim Niemueller [www.niemueller.de]
7  * 2010 Bahram Maleki-Fard
8  *
9  ****************************************************************************/
10 
11 /* This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version. A runtime exception applies to
15  * this software (see LICENSE.GPL_WRE file mentioned below for details).
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU Library General Public License for more details.
21  *
22  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
23  */
24 
25 #include <fvutils/draw/mono_drawer.h>
26 #include <fvutils/color/yuv.h>
27 
28 #include <cmath>
29 #include <algorithm>
30 #include <unistd.h>
31 
32 #define PUT_POINT( x, y ) \
33 { \
34  if( __overlap ) \
35  __buffer[ y * __width + x ] = std::min(255, __buffer[ y * __width + x ] + __brightness); \
36  else \
37  __buffer[ y * __width + x ] = __brightness; \
38 }
39 
40 namespace firevision {
41 #if 0 /* just to make Emacs auto-indent happy */
42 }
43 #endif
44 
45 /** @class MonoDrawer <fvutils/draw/mono_drawer.h>
46  * Draw to a monochrome image.
47  * @author Tim Niemueller (Base)
48  * @author Bahram Maleki-Fard (Modification)
49  */
50 
51 /** Constructor. */
53 {
54  __buffer = NULL;
55  __brightness = 1;
56  __overlap = 1;
57 }
58 
59 /** Destructor */
61 {
62 }
63 
64 
65 /** Set the buffer to draw to
66  * @param buffer buffer to draw to, must be MONO8 formatted. E.g. Y-plane of YUV
67  * @param width width of the buffer
68  * @param height height of the buffer
69  */
70 void
71 MonoDrawer::set_buffer(unsigned char *buffer,
72  unsigned int width, unsigned int height)
73 {
74  this->__buffer = buffer;
75  this->__width = width;
76  this->__height = height;
77 }
78 
79 
80 /** Set drawing brightness.
81  * @param b brightness; 0-255
82  */
83 void
85 {
86  __brightness = b;
87 }
88 
89 
90 /** Enable/Disable transparency (overlapping pixels increase brightness).
91  * @param o overlapping true/false
92  */
93 void
95 {
96  __overlap = o;
97 }
98 
99 
100 /** Draw circle.
101  * Draws a circle at the given center point and with the given radius.
102  * @param center_x x coordinate of circle center
103  * @param center_y y coordinate of circle center
104  * @param radius radius of circle
105  */
106 void
107 MonoDrawer::draw_circle(int center_x, int center_y, unsigned int radius)
108 {
109  if (__buffer == NULL) return;
110 
111  unsigned int x = 0,
112  y = radius,
113  r2 = radius * radius;
114 
115  unsigned int x_tmp, y_tmp;
116 
117  while (x <= y) {
118 
119  x_tmp = center_x + x;
120  y_tmp = center_y + y;
121  if ( (x_tmp < __width) && (y_tmp < __height) )
122  PUT_POINT( x_tmp, y_tmp );
123 
124  x_tmp = center_x - x;
125  y_tmp = center_y + y;
126  if ( (x_tmp < __width) && (y_tmp < __height) )
127  PUT_POINT( x_tmp, y_tmp );
128 
129  x_tmp = center_x + y;
130  y_tmp = center_y + x;
131  if ( (x_tmp < __width) && (y_tmp < __height) )
132  PUT_POINT( x_tmp, y_tmp );
133 
134  x_tmp = center_x - y;
135  y_tmp = center_y + x;
136  if ( (x_tmp < __width) && (y_tmp < __height) )
137  PUT_POINT( x_tmp, y_tmp );
138 
139  x_tmp = center_x + x;
140  y_tmp = center_y - y;
141  if ( (x_tmp < __width) && (y_tmp < __height) )
142  PUT_POINT( x_tmp, y_tmp );
143 
144  x_tmp = center_x - x;
145  y_tmp = center_y - y;
146  if ( (x_tmp < __width) && (y_tmp < __height) )
147  PUT_POINT( x_tmp, y_tmp );
148 
149  x_tmp = center_x + y;
150  y_tmp = center_y - x;
151  if ( (x_tmp < __width) && (y_tmp < __height) )
152  PUT_POINT( x_tmp, y_tmp );
153 
154  x_tmp = center_x - y;
155  y_tmp = center_y - x;
156  if ( (x_tmp < __width) && (y_tmp < __height) )
157  PUT_POINT( x_tmp, y_tmp );
158 
159  ++x;
160  y=(int)(sqrt((float)(r2 - x * x))+0.5);
161  }
162 
163 }
164 
165 
166 /** Draw rectangle.
167  * @param x x coordinate of rectangle's upper left corner
168  * @param y y coordinate of rectangle's upper left corner
169  * @param w width of rectangle from x to the right
170  * @param h height of rectangle from y to the bottom
171  */
172 void
173 MonoDrawer::draw_rectangle(unsigned int x, unsigned int y,
174  unsigned int w, unsigned int h)
175 {
176 
177  // horizontal line at top
178  for (unsigned int i = x; i < x + w; ++i) {
179  if ( i < __width ) {
180  PUT_POINT( i, y );
181  } else {
182  break;
183  }
184  }
185 
186  // left and right
187  for (unsigned int i = y; i < y + h; ++i) {
188  // left
189  PUT_POINT( x, i );
190 
191  if ( (x + w) < __width ) {
192  // right
193  PUT_POINT( x+w, i );
194  }
195  }
196 
197  // horizontal line at bottom
198  for (unsigned int i = x; i < x + w; ++i) {
199  if ( i < __width ) {
200  PUT_POINT( i, y+h );
201  } else {
202  break;
203  }
204  }
205 
206 }
207 
208 
209 /** Draw inverted rectangle.
210  * This draws a rectangle but instead of using the draw color it is drawn
211  * in the inverted color of the pixel where it is drawn.
212  * @param x x coordinate of rectangle's upper left corner
213  * @param y y coordinate of rectangle's upper left corner
214  * @param w width of rectangle from x to the right
215  * @param h height of rectangle from y to the bottom
216  */
217 void
218 MonoDrawer::draw_rectangle_inverted(unsigned int x, unsigned int y,
219  unsigned int w, unsigned int h)
220 {
221 
222  unsigned int ind = 0;
223 
224  // horizontal line at top
225  for (unsigned int i = x; i < x + w; ++i) {
226  if ( i < __width ) {
227  ind = y * __width + i;
228  __buffer[ind] = 255 - __buffer[ind];
229  } else {
230  break;
231  }
232  }
233 
234  // left and right
235  for (unsigned int i = y; i < y + h; ++i) {
236  // left
237  ind = i * __width + x;
238  __buffer[ind] = 255 - __buffer[ind];
239 
240  if ( (x + w) < __width ) {
241  // right
242  ind += w;
243  __buffer[ind] = 255 - __buffer[ind];
244  }
245  }
246 
247  // horizontal line at bottom
248  for (unsigned int i = x; i < x + w; ++i) {
249  if ( i < __width ) {
250  __buffer[ind] = 255 - __buffer[ind];
251  } else {
252  break;
253  }
254  }
255 
256 }
257 
258 
259 /** Draw point.
260  * @param x x coordinate of point
261  * @param y y coordinate of point
262  */
263 void
264 MonoDrawer::draw_point(unsigned int x, unsigned int y)
265 {
266  if ( x > __width) return;
267  if ( y > __height) return;
268 
269  PUT_POINT( x, y );
270 }
271 
272 
273 /** Draw line.
274  * Standard Bresenham in all directions. For in-depth information
275  * have a look at http://de.wikipedia.org/wiki/Bresenham-Algorithmus
276  * @param x_start x coordinate of start point
277  * @param y_start y coordinate of start point
278  * @param x_end x coordinate of end point
279  * @param y_end y coordinate of end point
280  */
281 void
282 MonoDrawer::draw_line(unsigned int x_start, unsigned int y_start,
283  unsigned int x_end, unsigned int y_end)
284 {
285  /* heavily inspired by an article on German Wikipedia about
286  * Bresenham's algorithm, confer
287  * http://de.wikipedia.org/wiki/Bresenham-Algorithmus
288  */
289 
290 
291  int x, y, dist, xerr, yerr, dx, dy, incx, incy;
292  bool was_inside_image = false;
293 
294  // calculate distance in both directions
295  dx = x_end - x_start;
296  dy = y_end - y_start;
297 
298  // Calculate sign of the increment
299  if(dx < 0) {
300  incx = -1;
301  dx = -dx;
302  } else {
303  incx = dx ? 1 : 0;
304  }
305 
306  if(dy < 0) {
307  incy = -1;
308  dy = -dy;
309  } else {
310  incy = dy ? 1 : 0;
311  }
312 
313  // check which distance is larger
314  dist = (dx > dy) ? dx : dy;
315 
316  // Initialize for loops
317  x = x_start;
318  y = y_start;
319  xerr = dx;
320  yerr = dy;
321 
322  /* Calculate and draw pixels */
323  for(int t = 0; t < dist; ++t) {
324  if ( ((unsigned int)x < __width) && ((unsigned int)y < __height) ) {
325  if ( (x >= 0) && (y >= 0) ) {
326  was_inside_image = true;
327  PUT_POINT( x, y );
328  }
329  } else {
330  if ( was_inside_image ) {
331  break;
332  }
333  }
334 
335  xerr += dx;
336  yerr += dy;
337 
338  if(xerr > dist) {
339  xerr -= dist;
340  x += incx;
341  }
342 
343  if(yerr>dist) {
344  yerr -= dist;
345  y += incy;
346  }
347  }
348 
349  if ( (x_end < __width) && (y_end < __height) ) {
350  PUT_POINT( x_end, y_end );
351  }
352 
353 }
354 
355 /** Draws a cross.
356  * @param x_center Center of the cross
357  * @param y_center Center of the cross
358  * @param width of the bars
359  */
360 void
361 MonoDrawer::draw_cross(unsigned int x_center, unsigned int y_center, unsigned int width)
362 {
363  x_center = std::min(x_center, __width);
364  y_center = std::min(y_center, __height);
365 
366  int r = width / 2;
367  unsigned int a = std::max(0, (int)x_center - r);
368  unsigned int b = std::min(x_center + r, __width);
369  draw_line(a, y_center, b, y_center);
370 
371  a = std::max(0, (int)y_center - r);
372  b = std::min(y_center + r, __height);
373  draw_line(x_center, a, x_center, b);
374 }
375 } // end namespace firevision
void set_buffer(unsigned char *buffer, unsigned int width, unsigned int height)
Set the buffer to draw to.
Definition: mono_drawer.cpp:71
void draw_circle(int center_x, int center_y, unsigned int radius)
Draw circle.
void set_overlap(bool o)
Enable/Disable transparency (overlapping pixels increase brightness).
Definition: mono_drawer.cpp:94
void draw_rectangle_inverted(unsigned int x, unsigned int y, unsigned int w, unsigned int h)
Draw inverted rectangle.
void draw_point(unsigned int x, unsigned int y)
Draw point.
void draw_cross(unsigned int x_center, unsigned int y_center, unsigned int width)
Draws a cross.
void set_brightness(unsigned char b)
Set drawing brightness.
Definition: mono_drawer.cpp:84
MonoDrawer()
Constructor.
Definition: mono_drawer.cpp:52
void draw_line(unsigned int x_start, unsigned int y_start, unsigned int x_end, unsigned int y_end)
Draw line.
~MonoDrawer()
Destructor.
Definition: mono_drawer.cpp:60
void draw_rectangle(unsigned int x, unsigned int y, unsigned int w, unsigned int h)
Draw rectangle.