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
40namespace 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 */
66void
67MonoDrawer::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 */
77void
79{
80 brightness_ = b;
81}
82
83/** Enable/Disable transparency (overlapping pixels increase brightness).
84 * @param o overlapping true/false
85 */
86void
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 */
98void
99MonoDrawer::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 */
160void
161MonoDrawer::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 */
201void
202MonoDrawer::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 */
243void
244MonoDrawer::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 */
262void
263MonoDrawer::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 */
341void
342MonoDrawer::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