mono_drawer.cpp

00001 
00002 /***************************************************************************
00003  *  mono_drawer.cpp - Utility to draw in a buffer
00004  *
00005  *  Generated: Wed Feb 08 20:55:38 2006
00006  *  Copyright  2005-2007  Tim Niemueller [www.niemueller.de]
00007  *             2010  Bahram Maleki-Fard
00008  *
00009  ****************************************************************************/
00010 
00011 /*  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version. A runtime exception applies to
00015  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00016  *
00017  *  This program is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  *  GNU Library General Public License for more details.
00021  *
00022  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00023  */
00024 
00025 #include <fvutils/draw/mono_drawer.h>
00026 #include <fvutils/color/yuv.h>
00027 
00028 #include <cmath>
00029 #include <algorithm>
00030 #include <unistd.h>
00031 
00032 #define PUT_POINT( x, y )                                                                       \
00033 {                                                                                               \
00034   if( __overlap )                                                                               \
00035     __buffer[ y * __width + x ]   = std::min(255, __buffer[ y * __width + x ] + __brightness);  \
00036   else                                                                                          \
00037     __buffer[ y * __width + x ]   = __brightness;                                               \
00038 }
00039 
00040 namespace firevision {
00041 #if 0 /* just to make Emacs auto-indent happy */
00042 }
00043 #endif
00044 
00045 /** @class MonoDrawer <fvutils/draw/mono_drawer.h>
00046  * Draw to a monochrome image.
00047  * @author Tim Niemueller (Base)
00048  * @author Bahram Maleki-Fard (Modification)
00049  */
00050 
00051 /** Constructor. */
00052 MonoDrawer::MonoDrawer()
00053 {
00054   __buffer = NULL;
00055   __brightness = 1;
00056   __overlap = 1;
00057 }
00058 
00059 /** Destructor */
00060 MonoDrawer::~MonoDrawer()
00061 {
00062 }
00063 
00064 
00065 /** Set the buffer to draw to
00066  * @param buffer buffer to draw to, must be MONO8 formatted. E.g. Y-plane of YUV
00067  * @param width width of the buffer
00068  * @param height height of the buffer
00069  */
00070 void
00071 MonoDrawer::set_buffer(unsigned char *buffer,
00072                   unsigned int width, unsigned int height)
00073 {
00074   this->__buffer     = buffer;
00075   this->__width      = width;
00076   this->__height     = height;
00077 }
00078 
00079 
00080 /** Set drawing brightness.
00081  * @param b brightness; 0-255
00082  */
00083 void
00084 MonoDrawer::set_brightness(unsigned char b)
00085 {
00086   __brightness = b;
00087 }
00088 
00089 
00090 /** Enable/Disable transparency (overlapping pixels increase brightness).
00091  * @param o overlapping true/false
00092  */
00093 void
00094 MonoDrawer::set_overlap(bool o)
00095 {
00096   __overlap = o;
00097 }
00098 
00099 
00100 /** Draw circle.
00101  * Draws a circle at the given center point and with the given radius.
00102  * @param center_x x coordinate of circle center
00103  * @param center_y y coordinate of circle center
00104  * @param radius radius of circle
00105  */
00106 void
00107 MonoDrawer::draw_circle(int center_x, int center_y, unsigned int radius)
00108 {
00109   if (__buffer == NULL) return;
00110 
00111   unsigned int x  = 0,
00112                y  = radius,
00113                r2 = radius * radius;
00114 
00115   unsigned int x_tmp, y_tmp;
00116 
00117   while (x <= y) {
00118 
00119     x_tmp = center_x + x;
00120     y_tmp = center_y + y;
00121     if ( (x_tmp < __width) && (y_tmp < __height) )
00122       PUT_POINT( x_tmp, y_tmp );
00123 
00124     x_tmp = center_x - x;
00125     y_tmp = center_y + y;
00126     if ( (x_tmp < __width) && (y_tmp < __height) )
00127       PUT_POINT( x_tmp, y_tmp );
00128 
00129     x_tmp = center_x + y;
00130     y_tmp = center_y + x;
00131     if ( (x_tmp < __width) && (y_tmp < __height) )
00132       PUT_POINT( x_tmp, y_tmp );
00133 
00134     x_tmp = center_x - y;
00135     y_tmp = center_y + x;
00136     if ( (x_tmp < __width) && (y_tmp < __height) )
00137       PUT_POINT( x_tmp, y_tmp );
00138 
00139     x_tmp = center_x + x;
00140     y_tmp = center_y - y;
00141     if ( (x_tmp < __width) && (y_tmp < __height) )
00142       PUT_POINT( x_tmp, y_tmp );
00143 
00144     x_tmp = center_x - x;
00145     y_tmp = center_y - y;
00146     if ( (x_tmp < __width) && (y_tmp < __height) )
00147       PUT_POINT( x_tmp, y_tmp );
00148 
00149     x_tmp = center_x + y;
00150     y_tmp = center_y - x;
00151     if ( (x_tmp < __width) && (y_tmp < __height) )
00152       PUT_POINT( x_tmp, y_tmp );
00153 
00154     x_tmp = center_x - y;
00155     y_tmp = center_y - x;
00156     if ( (x_tmp < __width) && (y_tmp < __height) )
00157       PUT_POINT( x_tmp, y_tmp );
00158 
00159     ++x;
00160     y=(int)(sqrt((float)(r2 - x * x))+0.5);
00161   }
00162 
00163 }
00164 
00165 
00166 /** Draw rectangle.
00167  * @param x x coordinate of rectangle's upper left corner
00168  * @param y y coordinate of rectangle's upper left corner
00169  * @param w width of rectangle from x to the right
00170  * @param h height of rectangle from y to the bottom
00171  */
00172 void
00173 MonoDrawer::draw_rectangle(unsigned int x, unsigned int y,
00174                       unsigned int w, unsigned int h)
00175 {
00176 
00177   // horizontal line at top
00178   for (unsigned int i = x; i < x + w; ++i) {
00179     if ( i < __width ) {
00180       PUT_POINT( i, y );
00181     } else {
00182       break;
00183     }
00184   }
00185 
00186   // left and right
00187   for (unsigned int i = y; i < y + h; ++i) {
00188     // left
00189     PUT_POINT( x, i );
00190 
00191     if ( (x + w) < __width ) {
00192       // right
00193       PUT_POINT( x+w, i );
00194     }
00195   }
00196 
00197   // horizontal line at bottom
00198   for (unsigned int i = x; i < x + w; ++i) {
00199     if ( i < __width ) {
00200       PUT_POINT( i, y+h );
00201     } else {
00202       break;
00203     }
00204   }
00205 
00206 }
00207 
00208 
00209 /** Draw inverted rectangle.
00210  * This draws a rectangle but instead of using the draw color it is drawn
00211  * in the inverted color of the pixel where it is drawn.
00212  * @param x x coordinate of rectangle's upper left corner
00213  * @param y y coordinate of rectangle's upper left corner
00214  * @param w width of rectangle from x to the right
00215  * @param h height of rectangle from y to the bottom
00216  */
00217 void
00218 MonoDrawer::draw_rectangle_inverted(unsigned int x, unsigned int y,
00219                               unsigned int w, unsigned int h)
00220 {
00221 
00222   unsigned int ind = 0;
00223 
00224   // horizontal line at top
00225   for (unsigned int i = x; i < x + w; ++i) {
00226     if ( i < __width ) {
00227       ind = y * __width + i;
00228       __buffer[ind]   = 255 - __buffer[ind];
00229     } else {
00230       break;
00231     }
00232   }
00233 
00234   // left and right
00235   for (unsigned int i = y; i < y + h; ++i) {
00236     // left
00237     ind = i * __width + x;
00238     __buffer[ind]   = 255 - __buffer[ind];
00239 
00240     if ( (x + w) < __width ) {
00241       // right
00242       ind += w;
00243       __buffer[ind]   = 255 - __buffer[ind];
00244     }
00245   }
00246 
00247   // horizontal line at bottom
00248   for (unsigned int i = x; i < x + w; ++i) {
00249     if ( i < __width ) {
00250       __buffer[ind]   = 255 - __buffer[ind];
00251     } else {
00252       break;
00253     }
00254   }
00255 
00256 }
00257 
00258 
00259 /** Draw point.
00260  * @param x x coordinate of point
00261  * @param y y coordinate of point
00262  */
00263 void
00264 MonoDrawer::draw_point(unsigned int x, unsigned int y)
00265 {
00266   if ( x > __width) return;
00267   if ( y > __height) return;
00268 
00269   PUT_POINT( x, y );
00270 }
00271 
00272 
00273 /** Draw line.
00274  * Standard Bresenham in all directions. For in-depth information
00275  * have a look at http://de.wikipedia.org/wiki/Bresenham-Algorithmus
00276  * @param x_start x coordinate of start point
00277  * @param y_start y coordinate of start point
00278  * @param x_end x coordinate of end point
00279  * @param y_end y coordinate of end point
00280  */
00281 void
00282 MonoDrawer::draw_line(unsigned int x_start, unsigned int y_start,
00283                  unsigned int x_end, unsigned int y_end)
00284 {
00285   /* heavily inspired by an article on German Wikipedia about
00286    * Bresenham's algorithm, confer
00287    * http://de.wikipedia.org/wiki/Bresenham-Algorithmus
00288    */
00289 
00290 
00291   int x, y, dist, xerr, yerr, dx, dy, incx, incy;
00292   bool was_inside_image = false;
00293 
00294   // calculate distance in both directions
00295   dx = x_end - x_start;
00296   dy = y_end - y_start;
00297 
00298   // Calculate sign of the increment
00299   if(dx < 0) {
00300     incx = -1;
00301     dx = -dx;
00302   } else {
00303     incx = dx ? 1 : 0;
00304   }
00305 
00306   if(dy < 0) {
00307     incy = -1;
00308     dy = -dy;
00309   } else {
00310     incy = dy ? 1 : 0;
00311   }
00312 
00313   // check which distance is larger
00314   dist = (dx > dy) ? dx : dy;
00315 
00316   // Initialize for loops
00317   x = x_start;
00318   y = y_start;
00319   xerr = dx;
00320   yerr = dy;
00321 
00322   /* Calculate and draw pixels */
00323   for(int t = 0; t < dist; ++t) {
00324     if ( ((unsigned int)x < __width) && ((unsigned int)y < __height) ) {
00325       if ( (x >= 0) && (y >= 0) ) {
00326         was_inside_image = true;
00327         PUT_POINT( x, y );
00328       }
00329     } else {
00330       if ( was_inside_image ) {
00331         break;
00332       }
00333     }
00334 
00335     xerr += dx;
00336     yerr += dy;
00337 
00338     if(xerr > dist) {
00339       xerr -= dist;
00340       x += incx;
00341     }
00342 
00343     if(yerr>dist) {
00344       yerr -= dist;
00345       y += incy;
00346     }
00347   }
00348 
00349   if ( (x_end < __width) && (y_end < __height) ) {
00350     PUT_POINT( x_end, y_end );
00351   }
00352 
00353 }
00354 
00355 /** Draws a cross.
00356  * @param x_center Center of the cross
00357  * @param y_center Center of the cross
00358  * @param width of the bars
00359  */
00360 void
00361 MonoDrawer::draw_cross(unsigned int x_center, unsigned int y_center, unsigned int width)
00362 {
00363   x_center = std::min(x_center, __width);
00364   y_center = std::min(y_center, __height);
00365 
00366   int r = width / 2;
00367   unsigned int a = std::max(0, (int)x_center - r);
00368   unsigned int b = std::min(x_center + r, __width);
00369   draw_line(a, y_center, b, y_center);
00370 
00371   a = std::max(0, (int)y_center - r);
00372   b = std::min(y_center + r, __height);
00373   draw_line(x_center, a, x_center, b);
00374 }
00375 } // end namespace firevision

Generated on 1 Mar 2011 for Fawkes API by  doxygen 1.6.1