00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <fvutils/draw/drawer.h>
00025 #include <fvutils/color/yuv.h>
00026
00027 #include <cmath>
00028 #include <algorithm>
00029 #include <unistd.h>
00030
00031
00032
00033
00034
00035
00036
00037
00038 Drawer::Drawer()
00039 {
00040 __buffer = NULL;
00041 __color = YUV_t::white();
00042 }
00043
00044
00045 Drawer::~Drawer()
00046 {
00047 }
00048
00049
00050
00051
00052
00053
00054
00055 void
00056 Drawer::set_buffer(unsigned char *buffer,
00057 unsigned int width, unsigned int height)
00058 {
00059 this->__buffer = buffer;
00060 this->__width = width;
00061 this->__height = height;
00062 }
00063
00064
00065
00066
00067
00068
00069
00070 void
00071 Drawer::set_color(unsigned char y, unsigned char u, unsigned char v)
00072 {
00073 __color.Y = y;
00074 __color.U = u;
00075 __color.V = v;
00076 }
00077
00078
00079
00080
00081
00082 void
00083 Drawer::set_color(YUV_t color)
00084 {
00085 __color = color;
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095 void
00096 Drawer::draw_circle(int center_x, int center_y, unsigned int radius)
00097 {
00098
00099 if (__buffer == NULL) return;
00100
00101 unsigned int x = 0,
00102 y = radius,
00103 r2 = radius * radius;
00104
00105 unsigned char *up = YUV422_PLANAR_U_PLANE(__buffer, __width, __height);
00106 unsigned char *vp = YUV422_PLANAR_V_PLANE(__buffer, __width, __height);
00107
00108 unsigned int x_tmp, y_tmp, ind_tmp;
00109
00110 while (x <= y) {
00111
00112 x_tmp = center_x + x;
00113 y_tmp = center_y + y;
00114 if ( (x_tmp < __width) && (y_tmp < __height) ) {
00115 ind_tmp = y_tmp * __width + x_tmp;
00116 __buffer[ind_tmp] = __color.Y;
00117 ind_tmp /= 2;
00118 up[ind_tmp] = __color.U;
00119 vp[ind_tmp] = __color.V;
00120 }
00121
00122 x_tmp = center_x - x;
00123 y_tmp = center_y + y;
00124 if ( (x_tmp < __width) && (y_tmp < __height) ) {
00125 ind_tmp = y_tmp * __width + x_tmp;
00126 __buffer[ind_tmp] = __color.Y;
00127 ind_tmp /= 2;
00128 up[ind_tmp] = __color.U;
00129 vp[ind_tmp] = __color.V;
00130 }
00131
00132 x_tmp = center_x + y;
00133 y_tmp = center_y + x;
00134 if ( (x_tmp < __width) && (y_tmp < __height) ) {
00135 ind_tmp = y_tmp * __width + x_tmp;
00136 __buffer[ind_tmp] = __color.Y;
00137 ind_tmp /= 2;
00138 up[ind_tmp] = __color.U;
00139 vp[ind_tmp] = __color.V;
00140 }
00141
00142 x_tmp = center_x - y;
00143 y_tmp = center_y + x;
00144 if ( (x_tmp < __width) && (y_tmp < __height) ) {
00145 ind_tmp = y_tmp * __width + x_tmp;
00146 __buffer[ind_tmp] = __color.Y;
00147 ind_tmp /= 2;
00148 up[ind_tmp] = __color.U;
00149 vp[ind_tmp] = __color.V;
00150 }
00151
00152 x_tmp = center_x + x;
00153 y_tmp = center_y - y;
00154 if ( (x_tmp < __width) && (y_tmp < __height) ) {
00155 ind_tmp = y_tmp * __width + x_tmp;
00156 __buffer[ind_tmp] = __color.Y;
00157 ind_tmp /= 2;
00158 up[ind_tmp] = __color.U;
00159 vp[ind_tmp] = __color.V;
00160 }
00161
00162 x_tmp = center_x - x;
00163 y_tmp = center_y - y;
00164 if ( (x_tmp < __width) && (y_tmp < __height)) {
00165 ind_tmp = y_tmp * __width + x_tmp;
00166 __buffer[ind_tmp] = __color.Y;
00167 ind_tmp /= 2;
00168 up[ind_tmp] = __color.U;
00169 vp[ind_tmp] = __color.V;
00170 }
00171
00172 x_tmp = center_x + y;
00173 y_tmp = center_y - x;
00174 if ( (x_tmp < __width) && (y_tmp < __height)) {
00175 ind_tmp = y_tmp * __width + x_tmp;
00176 __buffer[ind_tmp] = __color.Y;
00177 ind_tmp /= 2;
00178 up[ind_tmp] = __color.U;
00179 vp[ind_tmp] = __color.V;
00180 }
00181
00182 x_tmp = center_x - y;
00183 y_tmp = center_y - x;
00184 if ( (x_tmp < __width) && (y_tmp < __height) ) {
00185 ind_tmp = y_tmp * __width + x_tmp;
00186 __buffer[ind_tmp] = __color.Y;
00187 ind_tmp /= 2;
00188 up[ind_tmp] = __color.U;
00189 vp[ind_tmp] = __color.V;
00190 }
00191
00192 ++x;
00193 y=(int)(sqrt((float)(r2 - x * x))+0.5);
00194 }
00195
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205 void
00206 Drawer::draw_rectangle(unsigned int x, unsigned int y,
00207 unsigned int w, unsigned int h)
00208 {
00209
00210 unsigned char *up = YUV422_PLANAR_U_PLANE(__buffer, __width, __height);
00211 unsigned char *vp = YUV422_PLANAR_V_PLANE(__buffer, __width, __height);
00212
00213
00214 for (unsigned int i = x; i < x + w; ++i) {
00215 if ( i < __width ) {
00216 __buffer[ y * __width + i ] = __color.Y;
00217 up[ (y * __width + i) / 2 ] = __color.U;
00218 vp[ (y * __width + i) / 2 ] = __color.V;
00219 } else {
00220 break;
00221 }
00222 }
00223
00224
00225 for (unsigned int i = y; i < y + h; ++i) {
00226
00227 __buffer[ i * __width + x ] = __color.Y;
00228 up[ (i * __width + x) / 2 ] = __color.U;
00229 vp[ (i * __width + x) / 2 ] = __color.V;
00230
00231 if ( (x + w) < __width ) {
00232
00233 __buffer[ i * __width + x + w ] = __color.Y;
00234 up[ (i * __width + x + w) / 2 ] = __color.U;
00235 vp[ (i * __width + x + w) / 2 ] = __color.V;
00236 }
00237 }
00238
00239
00240 for (unsigned int i = x; i < x + w; ++i) {
00241 if ( i < __width ) {
00242 __buffer[ (y + h) * __width + i ] = __color.Y;
00243 up[ ((y + h) * __width + i) / 2 ] = __color.U;
00244 vp[ ((y + h) * __width + i) / 2 ] = __color.V;
00245 } else {
00246 break;
00247 }
00248 }
00249
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 void
00262 Drawer::draw_rectangle_inverted(unsigned int x, unsigned int y,
00263 unsigned int w, unsigned int h)
00264 {
00265
00266 unsigned int ind = 0;
00267
00268
00269 for (unsigned int i = x; i < x + w; ++i) {
00270 if ( i < __width ) {
00271 ind = y * __width + i;
00272 __buffer[ind] = 255 - __buffer[ind];
00273 } else {
00274 break;
00275 }
00276 }
00277
00278
00279 for (unsigned int i = y; i < y + h; ++i) {
00280
00281 ind = i * __width + x;
00282 __buffer[ind] = 255 - __buffer[ind];
00283
00284 if ( (x + w) < __width ) {
00285
00286 ind += w;
00287 __buffer[ind] = 255 - __buffer[ind];
00288 }
00289 }
00290
00291
00292 for (unsigned int i = x; i < x + w; ++i) {
00293 if ( i < __width ) {
00294 __buffer[ind] = 255 - __buffer[ind];
00295 } else {
00296 break;
00297 }
00298 }
00299
00300 }
00301
00302
00303
00304
00305
00306
00307 void
00308 Drawer::draw_point(unsigned int x, unsigned int y)
00309 {
00310 if ( x > __width) return;
00311 if ( y > __height) return;
00312
00313 unsigned char *up = YUV422_PLANAR_U_PLANE(__buffer, __width, __height);
00314 unsigned char *vp = YUV422_PLANAR_V_PLANE(__buffer, __width, __height);
00315
00316 __buffer[ y * __width + x ] = __color.Y;
00317 up[ (y * __width + x) / 2 ] = __color.U;
00318 vp[ (y * __width + x) / 2 ] = __color.V;
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 void
00330 Drawer::color_point(unsigned int x, unsigned int y)
00331 {
00332 if ( x > __width) return;
00333 if ( y > __height) return;
00334
00335 unsigned char *up = YUV422_PLANAR_U_PLANE(__buffer, __width, __height);
00336 unsigned char *vp = YUV422_PLANAR_V_PLANE(__buffer, __width, __height);
00337
00338 __buffer[ y * __width + x ] = __color.Y;
00339 up[ (y * __width + x) / 2 ] = __color.U;
00340 vp[ (y * __width + x) / 2 ] = __color.V;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 void
00352 Drawer::color_point(unsigned int x, unsigned int y, YUV_t color)
00353 {
00354 if ( x > __width) return;
00355 if ( y > __height) return;
00356
00357 unsigned char *up = YUV422_PLANAR_U_PLANE(__buffer, __width, __height);
00358 unsigned char *vp = YUV422_PLANAR_V_PLANE(__buffer, __width, __height);
00359
00360 __buffer[ y * __width + x ] = color.Y;
00361 up[ (y * __width + x) / 2 ] = color.U;
00362 vp[ (y * __width + x) / 2 ] = color.V;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 void
00375 Drawer::draw_line(unsigned int x_start, unsigned int y_start,
00376 unsigned int x_end, unsigned int y_end)
00377 {
00378
00379
00380
00381
00382
00383
00384 int x, y, dist, xerr, yerr, dx, dy, incx, incy;
00385 bool was_inside_image = false;
00386
00387 unsigned char *up = YUV422_PLANAR_U_PLANE(__buffer, __width, __height);
00388 unsigned char *vp = YUV422_PLANAR_V_PLANE(__buffer, __width, __height);
00389
00390
00391 dx = x_end - x_start;
00392 dy = y_end - y_start;
00393
00394
00395 if(dx < 0) {
00396 incx = -1;
00397 dx = -dx;
00398 } else {
00399 incx = dx ? 1 : 0;
00400 }
00401
00402 if(dy < 0) {
00403 incy = -1;
00404 dy = -dy;
00405 } else {
00406 incy = dy ? 1 : 0;
00407 }
00408
00409
00410 dist = (dx > dy) ? dx : dy;
00411
00412
00413 x = x_start;
00414 y = y_start;
00415 xerr = dx;
00416 yerr = dy;
00417
00418
00419 for(int t = 0; t < dist; ++t) {
00420 if ( ((unsigned int)x < __width) && ((unsigned int)y < __height) ) {
00421 if ( (x >= 0) && (y >= 0) ) {
00422 was_inside_image = true;
00423 __buffer[ y * __width + x ] = __color.Y;
00424 up[ (y * __width + x) / 2 ] = __color.U;
00425 vp[ (y * __width + x) / 2 ] = __color.V;
00426 }
00427 } else {
00428 if ( was_inside_image ) {
00429 break;
00430 }
00431 }
00432
00433 xerr += dx;
00434 yerr += dy;
00435
00436 if(xerr > dist) {
00437 xerr -= dist;
00438 x += incx;
00439 }
00440
00441 if(yerr>dist) {
00442 yerr -= dist;
00443 y += incy;
00444 }
00445 }
00446
00447 if ( (x_end < __width) && (y_end < __height) ) {
00448 __buffer[ y_end * __width + x_end ] = __color.Y;
00449 up[ (y_end * __width + x_end) / 2 ] = __color.U;
00450 vp[ (y_end * __width + x_end) / 2 ] = __color.V;
00451 }
00452
00453 }
00454
00455
00456
00457
00458
00459
00460 void
00461 Drawer::draw_cross(unsigned int x_center, unsigned int y_center, unsigned int width)
00462 {
00463 x_center = std::min(x_center, __width);
00464 y_center = std::min(y_center, __height);
00465
00466 int r = width / 2;
00467 unsigned int a = std::max(0, (int)x_center - r);
00468 unsigned int b = std::min(x_center + r, __width);
00469 draw_line(a, y_center, b, y_center);
00470
00471 a = std::max(0, (int)y_center - r);
00472 b = std::min(y_center + r, __height);
00473 draw_line(x_center, a, x_center, b);
00474 }
00475