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/color/yuv.h>
26 #include <fvutils/draw/mono_drawer.h>
27 
28 #include <algorithm>
29 #include <cmath>
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 
42 /** @class MonoDrawer <fvutils/draw/mono_drawer.h>
43  * Draw to a monochrome image.
44  * @author Tim Niemueller (Base)
45  * @author Bahram Maleki-Fard (Modification)
46  */
47 
48 /** Constructor. */
50 {
51  buffer_ = NULL;
52  brightness_ = 1;
53  overlap_ = 1;
54 }
55 
56 /** Destructor */
58 {
59 }
60 
61 /** Set the buffer to draw to
62  * @param buffer buffer to draw to, must be MONO8 formatted. E.g. Y-plane of YUV
63  * @param width width of the buffer
64  * @param height height of the buffer
65  */
66 void
67 MonoDrawer::set_buffer(unsigned char *buffer, unsigned int width, unsigned int height)
68 {
69  this->buffer_ = buffer;
70  this->width_ = width;
71  this->height_ = height;
72 }
73 
74 /** Set drawing brightness.
75  * @param b brightness; 0-255
76  */
77 void
79 {
80  brightness_ = b;
81 }
82 
83 /** Enable/Disable transparency (overlapping pixels increase brightness).
84  * @param o overlapping true/false
85  */
86 void
88 {
89  overlap_ = o;
90 }
91 
92 /** Draw circle.
93  * Draws a circle at the given center point and with the given radius.
94  * @param center_x x coordinate of circle center
95  * @param center_y y coordinate of circle center
96  * @param radius radius of circle
97  */
98 void
99 MonoDrawer::draw_circle(int center_x, int center_y, unsigned int radius)
100 {
101  if (buffer_ == NULL)
102  return;
103 
104  unsigned int x = 0, y = radius, r2 = radius * radius;
105 
106  unsigned int x_tmp, y_tmp;
107 
108  while (x <= y) {
109  x_tmp = center_x + x;
110  y_tmp = center_y + y;
111  if ((x_tmp < width_) && (y_tmp < height_))
112  PUT_POINT(x_tmp, y_tmp);
113 
114  x_tmp = center_x - x;
115  y_tmp = center_y + y;
116  if ((x_tmp < width_) && (y_tmp < height_))
117  PUT_POINT(x_tmp, y_tmp);
118 
119  x_tmp = center_x + y;
120  y_tmp = center_y + x;
121  if ((x_tmp < width_) && (y_tmp < height_))
122  PUT_POINT(x_tmp, y_tmp);
123 
124  x_tmp = center_x - y;
125  y_tmp = center_y + x;
126  if ((x_tmp < width_) && (y_tmp < height_))
127  PUT_POINT(x_tmp, y_tmp);
128 
129  x_tmp = center_x + x;
130  y_tmp = center_y - y;
131  if ((x_tmp < width_) && (y_tmp < height_))
132  PUT_POINT(x_tmp, y_tmp);
133 
134  x_tmp = center_x - x;
135  y_tmp = center_y - y;
136  if ((x_tmp < width_) && (y_tmp < height_))
137  PUT_POINT(x_tmp, y_tmp);
138 
139  x_tmp = center_x + y;
140  y_tmp = center_y - x;
141  if ((x_tmp < width_) && (y_tmp < height_))
142  PUT_POINT(x_tmp, y_tmp);
143 
144  x_tmp = center_x - y;
145  y_tmp = center_y - x;
146  if ((x_tmp < width_) && (y_tmp < height_))
147  PUT_POINT(x_tmp, y_tmp);
148 
149  ++x;
150  y = (int)(sqrt((float)(r2 - x * x)) + 0.5);
151  }
152 }
153 
154 /** Draw rectangle.
155  * @param x x coordinate of rectangle's upper left corner
156  * @param y y coordinate of rectangle's upper left corner
157  * @param w width of rectangle from x to the right
158  * @param h height of rectangle from y to the bottom
159  */
160 void
161 MonoDrawer::draw_rectangle(unsigned int x, unsigned int y, unsigned int w, unsigned int h)
162 {
163  // horizontal line at top
164  for (unsigned int i = x; i < x + w; ++i) {
165  if (i < width_) {
166  PUT_POINT(i, y);
167  } else {
168  break;
169  }
170  }
171 
172  // left and right
173  for (unsigned int i = y; i < y + h; ++i) {
174  // left
175  PUT_POINT(x, i);
176 
177  if ((x + w) < width_) {
178  // right
179  PUT_POINT(x + w, i);
180  }
181  }
182 
183  // horizontal line at bottom
184  for (unsigned int i = x; i < x + w; ++i) {
185  if (i < width_) {
186  PUT_POINT(i, y + h);
187  } else {
188  break;
189  }
190  }
191 }
192 
193 /** Draw inverted rectangle.
194  * This draws a rectangle but instead of using the draw color it is drawn
195  * in the inverted color of the pixel where it is drawn.
196  * @param x x coordinate of rectangle's upper left corner
197  * @param y y coordinate of rectangle's upper left corner
198  * @param w width of rectangle from x to the right
199  * @param h height of rectangle from y to the bottom
200  */
201 void
202 MonoDrawer::draw_rectangle_inverted(unsigned int x, unsigned int y, unsigned int w, unsigned int h)
203 {
204  unsigned int ind = 0;
205 
206  // horizontal line at top
207  for (unsigned int i = x; i < x + w; ++i) {
208  if (i < width_) {
209  ind = y * width_ + i;
210  buffer_[ind] = 255 - buffer_[ind];
211  } else {
212  break;
213  }
214  }
215 
216  // left and right
217  for (unsigned int i = y; i < y + h; ++i) {
218  // left
219  ind = i * width_ + x;
220  buffer_[ind] = 255 - buffer_[ind];
221 
222  if ((x + w) < width_) {
223  // right
224  ind += w;
225  buffer_[ind] = 255 - buffer_[ind];
226  }
227  }
228 
229  // horizontal line at bottom
230  for (unsigned int i = x; i < x + w; ++i) {
231  if (i < width_) {
232  buffer_[ind] = 255 - buffer_[ind];
233  } else {
234  break;
235  }
236  }
237 }
238 
239 /** Draw point.
240  * @param x x coordinate of point
241  * @param y y coordinate of point
242  */
243 void
244 MonoDrawer::draw_point(unsigned int x, unsigned int y)
245 {
246  if (x > width_)
247  return;
248  if (y > height_)
249  return;
250 
251  PUT_POINT(x, y);
252 }
253 
254 /** Draw line.
255  * Standard Bresenham in all directions. For in-depth information
256  * have a look at http://de.wikipedia.org/wiki/Bresenham-Algorithmus
257  * @param x_start x coordinate of start point
258  * @param y_start y coordinate of start point
259  * @param x_end x coordinate of end point
260  * @param y_end y coordinate of end point
261  */
262 void
263 MonoDrawer::draw_line(unsigned int x_start,
264  unsigned int y_start,
265  unsigned int x_end,
266  unsigned int y_end)
267 {
268  /* heavily inspired by an article on German Wikipedia about
269  * Bresenham's algorithm, confer
270  * http://de.wikipedia.org/wiki/Bresenham-Algorithmus
271  */
272 
273  int x, y, dist, xerr, yerr, dx, dy, incx, incy;
274  bool was_inside_image = false;
275 
276  // calculate distance in both directions
277  dx = x_end - x_start;
278  dy = y_end - y_start;
279 
280  // Calculate sign of the increment
281  if (dx < 0) {
282  incx = -1;
283  dx = -dx;
284  } else {
285  incx = dx ? 1 : 0;
286  }
287 
288  if (dy < 0) {
289  incy = -1;
290  dy = -dy;
291  } else {
292  incy = dy ? 1 : 0;
293  }
294 
295  // check which distance is larger
296  dist = (dx > dy) ? dx : dy;
297 
298  // Initialize for loops
299  x = x_start;
300  y = y_start;
301  xerr = dx;
302  yerr = dy;
303 
304  /* Calculate and draw pixels */
305  for (int t = 0; t < dist; ++t) {
306  if (((unsigned int)x < width_) && ((unsigned int)y < height_)) {
307  if ((x >= 0) && (y >= 0)) {
308  was_inside_image = true;
309  PUT_POINT(x, y);
310  }
311  } else {
312  if (was_inside_image) {
313  break;
314  }
315  }
316 
317  xerr += dx;
318  yerr += dy;
319 
320  if (xerr > dist) {
321  xerr -= dist;
322  x += incx;
323  }
324 
325  if (yerr > dist) {
326  yerr -= dist;
327  y += incy;
328  }
329  }
330 
331  if ((x_end < width_) && (y_end < height_)) {
332  PUT_POINT(x_end, y_end);
333  }
334 }
335 
336 /** Draws a cross.
337  * @param x_center Center of the cross
338  * @param y_center Center of the cross
339  * @param width of the bars
340  */
341 void
342 MonoDrawer::draw_cross(unsigned int x_center, unsigned int y_center, unsigned int width)
343 {
344  x_center = std::min(x_center, width_);
345  y_center = std::min(y_center, height_);
346 
347  int r = width / 2;
348  unsigned int a = std::max(0, (int)x_center - r);
349  unsigned int b = std::min(x_center + r, width_);
350  draw_line(a, y_center, b, y_center);
351 
352  a = std::max(0, (int)y_center - r);
353  b = std::min(y_center + r, height_);
354  draw_line(x_center, a, x_center, b);
355 }
356 } // end namespace firevision
MonoDrawer()
Constructor.
Definition: mono_drawer.cpp:49
void set_brightness(unsigned char b)
Set drawing brightness.
Definition: mono_drawer.cpp:78
void draw_rectangle(unsigned int x, unsigned int y, unsigned int w, unsigned int h)
Draw rectangle.
~MonoDrawer()
Destructor.
Definition: mono_drawer.cpp:57
void draw_cross(unsigned int x_center, unsigned int y_center, unsigned int width)
Draws a cross.
void set_overlap(bool o)
Enable/Disable transparency (overlapping pixels increase brightness).
Definition: mono_drawer.cpp:87
void draw_circle(int center_x, int center_y, unsigned int radius)
Draw circle.
Definition: mono_drawer.cpp:99
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_line(unsigned int x_start, unsigned int y_start, unsigned int x_end, unsigned int y_end)
Draw line.
void set_buffer(unsigned char *buffer, unsigned int width, unsigned int height)
Set the buffer to draw to.
Definition: mono_drawer.cpp:67