Fawkes API Fawkes Development Version
|
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