cxdrawing.cpp revision 6acb9a7ea3d7564944e12cbc73a857b88c1301ee
1/*M/////////////////////////////////////////////////////////////////////////////////////// 2// 3// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4// 5// By downloading, copying, installing or using the software you agree to this license. 6// If you do not agree to this license, do not download, install, 7// copy or use the software. 8// 9// 10// Intel License Agreement 11// For Open Source Computer Vision Library 12// 13// Copyright (C) 2000, Intel Corporation, all rights reserved. 14// Third party copyrights are property of their respective owners. 15// 16// Redistribution and use in source and binary forms, with or without modification, 17// are permitted provided that the following conditions are met: 18// 19// * Redistribution's of source code must retain the above copyright notice, 20// this list of conditions and the following disclaimer. 21// 22// * Redistribution's in binary form must reproduce the above copyright notice, 23// this list of conditions and the following disclaimer in the documentation 24// and/or other materials provided with the distribution. 25// 26// * The name of Intel Corporation may not be used to endorse or promote products 27// derived from this software without specific prior written permission. 28// 29// This software is provided by the copyright holders and contributors "as is" and 30// any express or implied warranties, including, but not limited to, the implied 31// warranties of merchantability and fitness for a particular purpose are disclaimed. 32// In no event shall the Intel Corporation or contributors be liable for any direct, 33// indirect, incidental, special, exemplary, or consequential damages 34// (including, but not limited to, procurement of substitute goods or services; 35// loss of use, data, or profits; or business interruption) however caused 36// and on any theory of liability, whether in contract, strict liability, 37// or tort (including negligence or otherwise) arising in any way out of 38// the use of this software, even if advised of the possibility of such damage. 39// 40//M*/ 41#include "_cxcore.h" 42 43#define XY_SHIFT 16 44#define XY_ONE (1 << XY_SHIFT) 45 46#define CV_DRAWING_STORAGE_BLOCK ((1 << 12) - 256) 47 48typedef struct CvPolyEdge 49{ 50 int x, dx; 51 union 52 { 53 struct CvPolyEdge *next; 54 int y0; 55 }; 56 int y1; 57} 58CvPolyEdge; 59 60static void 61icvCollectPolyEdges( CvMat* img, CvSeq* v, CvContour* edges, 62 const void* color, int line_type, 63 int shift, CvPoint offset=cvPoint(0,0) ); 64 65static void 66icvFillEdgeCollection( CvMat* img, CvContour* edges, const void* color ); 67 68static void 69icvPolyLine( CvMat* img, CvPoint *v, int count, int closed, 70 const void* color, int thickness, int line_type, int shift ); 71 72static void 73icvFillConvexPoly( CvMat* img, CvPoint* v, int npts, 74 const void* color, int line_type, int shift ); 75 76/****************************************************************************************\ 77* Lines * 78\****************************************************************************************/ 79 80CV_IMPL int 81cvClipLine( CvSize img_size, CvPoint* pt1, CvPoint* pt2 ) 82{ 83 int result = 0; 84 85 CV_FUNCNAME( "cvClipLine" ); 86 87 __BEGIN__; 88 89 int x1, y1, x2, y2; 90 int c1, c2; 91 int right = img_size.width-1, bottom = img_size.height-1; 92 93 if( !pt1 || !pt2 ) 94 CV_ERROR( CV_StsNullPtr, "One of point pointers is NULL" ); 95 96 if( right < 0 || bottom < 0 ) 97 CV_ERROR( CV_StsOutOfRange, "Image width or height are negative" ); 98 99 x1 = pt1->x; y1 = pt1->y; x2 = pt2->x; y2 = pt2->y; 100 c1 = (x1 < 0) + (x1 > right) * 2 + (y1 < 0) * 4 + (y1 > bottom) * 8; 101 c2 = (x2 < 0) + (x2 > right) * 2 + (y2 < 0) * 4 + (y2 > bottom) * 8; 102 103 if( (c1 & c2) == 0 && (c1 | c2) != 0 ) 104 { 105 int a; 106 107 if( c1 & 12 ) 108 { 109 a = c1 < 8 ? 0 : bottom; 110 x1 += (int) (((int64) (a - y1)) * (x2 - x1) / (y2 - y1)); 111 y1 = a; 112 c1 = (x1 < 0) + (x1 > right) * 2; 113 } 114 if( c2 & 12 ) 115 { 116 a = c2 < 8 ? 0 : bottom; 117 x2 += (int) (((int64) (a - y2)) * (x2 - x1) / (y2 - y1)); 118 y2 = a; 119 c2 = (x2 < 0) + (x2 > right) * 2; 120 } 121 if( (c1 & c2) == 0 && (c1 | c2) != 0 ) 122 { 123 if( c1 ) 124 { 125 a = c1 == 1 ? 0 : right; 126 y1 += (int) (((int64) (a - x1)) * (y2 - y1) / (x2 - x1)); 127 x1 = a; 128 c1 = 0; 129 } 130 if( c2 ) 131 { 132 a = c2 == 1 ? 0 : right; 133 y2 += (int) (((int64) (a - x2)) * (y2 - y1) / (x2 - x1)); 134 x2 = a; 135 c2 = 0; 136 } 137 } 138 139 assert( (c1 & c2) != 0 || (x1 | y1 | x2 | y2) >= 0 ); 140 141 pt1->x = x1; 142 pt1->y = y1; 143 pt2->x = x2; 144 pt2->y = y2; 145 } 146 147 result = ( c1 | c2 ) == 0; 148 149 __END__; 150 151 return result; 152} 153 154 155/* 156 Initializes line iterator. 157 Returns number of points on the line or negative number if error. 158*/ 159CV_IMPL int 160cvInitLineIterator( const CvArr* img, CvPoint pt1, CvPoint pt2, 161 CvLineIterator* iterator, int connectivity, 162 int left_to_right ) 163{ 164 int count = -1; 165 166 CV_FUNCNAME( "cvInitLineIterator" ); 167 168 __BEGIN__; 169 170 CvMat stub, *mat = (CvMat*)img; 171 int dx, dy, s; 172 int bt_pix, bt_pix0, step; 173 174 if( !CV_IS_MAT(mat) ) 175 CV_CALL( mat = cvGetMat( mat, &stub )); 176 177 if( !iterator ) 178 CV_ERROR( CV_StsNullPtr, "Pointer to the iterator state is NULL" ); 179 180 if( connectivity != 8 && connectivity != 4 ) 181 CV_ERROR( CV_StsBadArg, "Connectivity must be 8 or 4" ); 182 183 if( (unsigned)pt1.x >= (unsigned)(mat->width) || 184 (unsigned)pt2.x >= (unsigned)(mat->width) || 185 (unsigned)pt1.y >= (unsigned)(mat->height) || 186 (unsigned)pt2.y >= (unsigned)(mat->height) ) 187 CV_ERROR( CV_StsBadPoint, 188 "One of the ending points is outside of the image, use cvClipLine" ); 189 190 bt_pix0 = bt_pix = CV_ELEM_SIZE(mat->type); 191 step = mat->step; 192 193 dx = pt2.x - pt1.x; 194 dy = pt2.y - pt1.y; 195 s = dx < 0 ? -1 : 0; 196 197 if( left_to_right ) 198 { 199 dx = (dx ^ s) - s; 200 dy = (dy ^ s) - s; 201 pt1.x ^= (pt1.x ^ pt2.x) & s; 202 pt1.y ^= (pt1.y ^ pt2.y) & s; 203 } 204 else 205 { 206 dx = (dx ^ s) - s; 207 bt_pix = (bt_pix ^ s) - s; 208 } 209 210 iterator->ptr = (uchar*)(mat->data.ptr + pt1.y * step + pt1.x * bt_pix0); 211 212 s = dy < 0 ? -1 : 0; 213 dy = (dy ^ s) - s; 214 step = (step ^ s) - s; 215 216 s = dy > dx ? -1 : 0; 217 218 /* conditional swaps */ 219 dx ^= dy & s; 220 dy ^= dx & s; 221 dx ^= dy & s; 222 223 bt_pix ^= step & s; 224 step ^= bt_pix & s; 225 bt_pix ^= step & s; 226 227 if( connectivity == 8 ) 228 { 229 assert( dx >= 0 && dy >= 0 ); 230 231 iterator->err = dx - (dy + dy); 232 iterator->plus_delta = dx + dx; 233 iterator->minus_delta = -(dy + dy); 234 iterator->plus_step = step; 235 iterator->minus_step = bt_pix; 236 count = dx + 1; 237 } 238 else /* connectivity == 4 */ 239 { 240 assert( dx >= 0 && dy >= 0 ); 241 242 iterator->err = 0; 243 iterator->plus_delta = (dx + dx) + (dy + dy); 244 iterator->minus_delta = -(dy + dy); 245 iterator->plus_step = step - bt_pix; 246 iterator->minus_step = bt_pix; 247 count = dx + dy + 1; 248 } 249 250 __END__; 251 252 return count; 253} 254 255static void 256icvLine( CvMat* mat, CvPoint pt1, CvPoint pt2, 257 const void* color, int connectivity = 8 ) 258{ 259 if( cvClipLine( cvGetMatSize(mat), &pt1, &pt2 )) 260 { 261 CvLineIterator iterator; 262 int pix_size = CV_ELEM_SIZE(mat->type); 263 int i, count; 264 265 if( connectivity == 0 ) 266 connectivity = 8; 267 if( connectivity == 1 ) 268 connectivity = 4; 269 270 count = cvInitLineIterator( mat, pt1, pt2, &iterator, connectivity, 1 ); 271 272 for( i = 0; i < count; i++ ) 273 { 274 CV_MEMCPY_AUTO( iterator.ptr, color, pix_size ); 275 CV_NEXT_LINE_POINT( iterator ); 276 } 277 } 278} 279 280 281/* Correction table depent on the slope */ 282static const uchar icvSlopeCorrTable[] = { 283 181, 181, 181, 182, 182, 183, 184, 185, 187, 188, 190, 192, 194, 196, 198, 201, 284 203, 206, 209, 211, 214, 218, 221, 224, 227, 231, 235, 238, 242, 246, 250, 254 285}; 286 287/* Gaussian for antialiasing filter */ 288static const int icvFilterTable[] = { 289 168, 177, 185, 194, 202, 210, 218, 224, 231, 236, 241, 246, 249, 252, 254, 254, 290 254, 254, 252, 249, 246, 241, 236, 231, 224, 218, 210, 202, 194, 185, 177, 168, 291 158, 149, 140, 131, 122, 114, 105, 97, 89, 82, 75, 68, 62, 56, 50, 45, 292 40, 36, 32, 28, 25, 22, 19, 16, 14, 12, 11, 9, 8, 7, 5, 5 293}; 294 295static void 296icvLineAA( CvMat* img, CvPoint pt1, CvPoint pt2, 297 const void* color ) 298{ 299 int dx, dy; 300 int ecount, scount = 0; 301 int slope; 302 int ax, ay; 303 int x_step, y_step; 304 int i, j; 305 int ep_table[9]; 306 int cb = ((uchar*)color)[0], cg = ((uchar*)color)[1], cr = ((uchar*)color)[2]; 307 int _cb, _cg, _cr; 308 int nch = CV_MAT_CN( img->type ); 309 uchar* ptr = (uchar*)(img->data.ptr); 310 int step = img->step; 311 CvSize size = cvGetMatSize( img ); 312 313 assert( img && (nch == 1 || nch == 3) && CV_MAT_DEPTH(img->type) == CV_8U ); 314 315 pt1.x -= XY_ONE*2; 316 pt1.y -= XY_ONE*2; 317 pt2.x -= XY_ONE*2; 318 pt2.y -= XY_ONE*2; 319 ptr += img->step*2 + 2*nch; 320 321 size.width = ((size.width - 5) << XY_SHIFT) + 1; 322 size.height = ((size.height - 5) << XY_SHIFT) + 1; 323 324 if( !cvClipLine( size, &pt1, &pt2 )) 325 return; 326 327 dx = pt2.x - pt1.x; 328 dy = pt2.y - pt1.y; 329 330 j = dx < 0 ? -1 : 0; 331 ax = (dx ^ j) - j; 332 i = dy < 0 ? -1 : 0; 333 ay = (dy ^ i) - i; 334 335 if( ax > ay ) 336 { 337 dx = ax; 338 dy = (dy ^ j) - j; 339 pt1.x ^= pt2.x & j; 340 pt2.x ^= pt1.x & j; 341 pt1.x ^= pt2.x & j; 342 pt1.y ^= pt2.y & j; 343 pt2.y ^= pt1.y & j; 344 pt1.y ^= pt2.y & j; 345 346 x_step = XY_ONE; 347 y_step = (int) (((int64) dy << XY_SHIFT) / (ax | 1)); 348 pt2.x += XY_ONE; 349 ecount = (pt2.x >> XY_SHIFT) - (pt1.x >> XY_SHIFT); 350 j = -(pt1.x & (XY_ONE - 1)); 351 pt1.y += (int) ((((int64) y_step) * j) >> XY_SHIFT) + (XY_ONE >> 1); 352 slope = (y_step >> (XY_SHIFT - 5)) & 0x3f; 353 slope ^= (y_step < 0 ? 0x3f : 0); 354 355 /* Get 4-bit fractions for end-point adjustments */ 356 i = (pt1.x >> (XY_SHIFT - 7)) & 0x78; 357 j = (pt2.x >> (XY_SHIFT - 7)) & 0x78; 358 } 359 else 360 { 361 dy = ay; 362 dx = (dx ^ i) - i; 363 pt1.x ^= pt2.x & i; 364 pt2.x ^= pt1.x & i; 365 pt1.x ^= pt2.x & i; 366 pt1.y ^= pt2.y & i; 367 pt2.y ^= pt1.y & i; 368 pt1.y ^= pt2.y & i; 369 370 x_step = (int) (((int64) dx << XY_SHIFT) / (ay | 1)); 371 y_step = XY_ONE; 372 pt2.y += XY_ONE; 373 ecount = (pt2.y >> XY_SHIFT) - (pt1.y >> XY_SHIFT); 374 j = -(pt1.y & (XY_ONE - 1)); 375 pt1.x += (int) ((((int64) x_step) * j) >> XY_SHIFT) + (XY_ONE >> 1); 376 slope = (x_step >> (XY_SHIFT - 5)) & 0x3f; 377 slope ^= (x_step < 0 ? 0x3f : 0); 378 379 /* Get 4-bit fractions for end-point adjustments */ 380 i = (pt1.y >> (XY_SHIFT - 7)) & 0x78; 381 j = (pt2.y >> (XY_SHIFT - 7)) & 0x78; 382 } 383 384 slope = (slope & 0x20) ? 0x100 : icvSlopeCorrTable[slope]; 385 386 /* Calc end point correction table */ 387 { 388 int t0 = slope << 7; 389 int t1 = ((0x78 - i) | 4) * slope; 390 int t2 = (j | 4) * slope; 391 392 ep_table[0] = 0; 393 ep_table[8] = slope; 394 ep_table[1] = ep_table[3] = ((((j - i) & 0x78) | 4) * slope >> 8) & 0x1ff; 395 ep_table[2] = (t1 >> 8) & 0x1ff; 396 ep_table[4] = ((((j - i) + 0x80) | 4) * slope >> 8) & 0x1ff; 397 ep_table[5] = ((t1 + t0) >> 8) & 0x1ff; 398 ep_table[6] = (t2 >> 8) & 0x1ff; 399 ep_table[7] = ((t2 + t0) >> 8) & 0x1ff; 400 } 401 402 if( nch == 3 ) 403 { 404 #define ICV_PUT_POINT() \ 405 { \ 406 _cb = tptr[0]; \ 407 _cb += ((cb - _cb)*a + 127)>> 8;\ 408 _cg = tptr[1]; \ 409 _cg += ((cg - _cg)*a + 127)>> 8;\ 410 _cr = tptr[2]; \ 411 _cr += ((cr - _cr)*a + 127)>> 8;\ 412 tptr[0] = (uchar)_cb; \ 413 tptr[1] = (uchar)_cg; \ 414 tptr[2] = (uchar)_cr; \ 415 } 416 if( ax > ay ) 417 { 418 ptr += (pt1.x >> XY_SHIFT) * 3; 419 420 while( ecount >= 0 ) 421 { 422 uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step; 423 424 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 + 425 (((ecount >= 2) + 1) & (ecount | 2))]; 426 int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31; 427 428 a = (ep_corr * icvFilterTable[dist + 32] >> 8) & 0xff; 429 ICV_PUT_POINT(); 430 ICV_PUT_POINT(); 431 432 tptr += step; 433 a = (ep_corr * icvFilterTable[dist] >> 8) & 0xff; 434 ICV_PUT_POINT(); 435 ICV_PUT_POINT(); 436 437 tptr += step; 438 a = (ep_corr * icvFilterTable[63 - dist] >> 8) & 0xff; 439 ICV_PUT_POINT(); 440 ICV_PUT_POINT(); 441 442 pt1.y += y_step; 443 ptr += 3; 444 scount++; 445 ecount--; 446 } 447 } 448 else 449 { 450 ptr += (pt1.y >> XY_SHIFT) * step; 451 452 while( ecount >= 0 ) 453 { 454 uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1) * 3; 455 456 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 + 457 (((ecount >= 2) + 1) & (ecount | 2))]; 458 int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31; 459 460 a = (ep_corr * icvFilterTable[dist + 32] >> 8) & 0xff; 461 ICV_PUT_POINT(); 462 ICV_PUT_POINT(); 463 464 tptr += 3; 465 a = (ep_corr * icvFilterTable[dist] >> 8) & 0xff; 466 ICV_PUT_POINT(); 467 ICV_PUT_POINT(); 468 469 tptr += 3; 470 a = (ep_corr * icvFilterTable[63 - dist] >> 8) & 0xff; 471 ICV_PUT_POINT(); 472 ICV_PUT_POINT(); 473 474 pt1.x += x_step; 475 ptr += step; 476 scount++; 477 ecount--; 478 } 479 } 480 #undef ICV_PUT_POINT 481 } 482 else 483 { 484 #define ICV_PUT_POINT() \ 485 { \ 486 _cb = tptr[0]; \ 487 _cb += ((cb - _cb)*a + 127)>> 8;\ 488 tptr[0] = (uchar)_cb; \ 489 } 490 491 if( ax > ay ) 492 { 493 ptr += (pt1.x >> XY_SHIFT); 494 495 while( ecount >= 0 ) 496 { 497 uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step; 498 499 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 + 500 (((ecount >= 2) + 1) & (ecount | 2))]; 501 int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31; 502 503 a = (ep_corr * icvFilterTable[dist + 32] >> 8) & 0xff; 504 ICV_PUT_POINT(); 505 ICV_PUT_POINT(); 506 507 tptr += step; 508 a = (ep_corr * icvFilterTable[dist] >> 8) & 0xff; 509 ICV_PUT_POINT(); 510 ICV_PUT_POINT(); 511 512 tptr += step; 513 a = (ep_corr * icvFilterTable[63 - dist] >> 8) & 0xff; 514 ICV_PUT_POINT(); 515 ICV_PUT_POINT(); 516 517 pt1.y += y_step; 518 ptr++; 519 scount++; 520 ecount--; 521 } 522 } 523 else 524 { 525 ptr += (pt1.y >> XY_SHIFT) * step; 526 527 while( ecount >= 0 ) 528 { 529 uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1); 530 531 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 + 532 (((ecount >= 2) + 1) & (ecount | 2))]; 533 int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31; 534 535 a = (ep_corr * icvFilterTable[dist + 32] >> 8) & 0xff; 536 ICV_PUT_POINT(); 537 ICV_PUT_POINT(); 538 539 tptr++; 540 a = (ep_corr * icvFilterTable[dist] >> 8) & 0xff; 541 ICV_PUT_POINT(); 542 ICV_PUT_POINT(); 543 544 tptr++; 545 a = (ep_corr * icvFilterTable[63 - dist] >> 8) & 0xff; 546 ICV_PUT_POINT(); 547 ICV_PUT_POINT(); 548 549 pt1.x += x_step; 550 ptr += step; 551 scount++; 552 ecount--; 553 } 554 } 555 #undef ICV_PUT_POINT 556 } 557} 558 559 560static void 561icvLine2( CvMat* img, CvPoint pt1, CvPoint pt2, const void* color ) 562{ 563 int dx, dy; 564 int ecount; 565 int ax, ay; 566 int i, j; 567 int x_step, y_step; 568 int cb = ((uchar*)color)[0]; 569 int cg = ((uchar*)color)[1]; 570 int cr = ((uchar*)color)[2]; 571 int pix_size = CV_ELEM_SIZE( img->type ); 572 uchar *ptr = (uchar*)(img->data.ptr), *tptr; 573 int step = img->step; 574 CvSize size = cvGetMatSize( img ); 575 576 //assert( img && (nch == 1 || nch == 3) && CV_MAT_DEPTH(img->type) == CV_8U ); 577 578 pt1.x -= XY_ONE*2; 579 pt1.y -= XY_ONE*2; 580 pt2.x -= XY_ONE*2; 581 pt2.y -= XY_ONE*2; 582 ptr += img->step*2 + 2*pix_size; 583 584 size.width = ((size.width - 5) << XY_SHIFT) + 1; 585 size.height = ((size.height - 5) << XY_SHIFT) + 1; 586 587 if( !cvClipLine( size, &pt1, &pt2 )) 588 return; 589 590 dx = pt2.x - pt1.x; 591 dy = pt2.y - pt1.y; 592 593 j = dx < 0 ? -1 : 0; 594 ax = (dx ^ j) - j; 595 i = dy < 0 ? -1 : 0; 596 ay = (dy ^ i) - i; 597 598 if( ax > ay ) 599 { 600 dx = ax; 601 dy = (dy ^ j) - j; 602 pt1.x ^= pt2.x & j; 603 pt2.x ^= pt1.x & j; 604 pt1.x ^= pt2.x & j; 605 pt1.y ^= pt2.y & j; 606 pt2.y ^= pt1.y & j; 607 pt1.y ^= pt2.y & j; 608 609 x_step = XY_ONE; 610 y_step = (int) (((int64) dy << XY_SHIFT) / (ax | 1)); 611 ecount = (pt2.x - pt1.x) >> XY_SHIFT; 612 } 613 else 614 { 615 dy = ay; 616 dx = (dx ^ i) - i; 617 pt1.x ^= pt2.x & i; 618 pt2.x ^= pt1.x & i; 619 pt1.x ^= pt2.x & i; 620 pt1.y ^= pt2.y & i; 621 pt2.y ^= pt1.y & i; 622 pt1.y ^= pt2.y & i; 623 624 x_step = (int) (((int64) dx << XY_SHIFT) / (ay | 1)); 625 y_step = XY_ONE; 626 ecount = (pt2.y - pt1.y) >> XY_SHIFT; 627 } 628 629 pt1.x += (XY_ONE >> 1); 630 pt1.y += (XY_ONE >> 1); 631 632 if( pix_size == 3 ) 633 { 634 #define ICV_PUT_POINT() \ 635 { \ 636 tptr[0] = (uchar)cb; \ 637 tptr[1] = (uchar)cg; \ 638 tptr[2] = (uchar)cr; \ 639 } 640 641 tptr = ptr + ((pt2.x + (XY_ONE >> 1))>> XY_SHIFT)*3 + 642 ((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)*step; 643 ICV_PUT_POINT(); 644 645 if( ax > ay ) 646 { 647 ptr += (pt1.x >> XY_SHIFT) * 3; 648 649 while( ecount >= 0 ) 650 { 651 tptr = ptr + (pt1.y >> XY_SHIFT) * step; 652 ICV_PUT_POINT(); 653 pt1.y += y_step; 654 ptr += 3; 655 ecount--; 656 } 657 } 658 else 659 { 660 ptr += (pt1.y >> XY_SHIFT) * step; 661 662 while( ecount >= 0 ) 663 { 664 tptr = ptr + (pt1.x >> XY_SHIFT) * 3; 665 ICV_PUT_POINT(); 666 pt1.x += x_step; 667 ptr += step; 668 ecount--; 669 } 670 } 671 672 #undef ICV_PUT_POINT 673 } 674 else if( pix_size == 1 ) 675 { 676 #define ICV_PUT_POINT() \ 677 { \ 678 tptr[0] = (uchar)cb; \ 679 } 680 681 tptr = ptr + ((pt2.x + (XY_ONE >> 1))>> XY_SHIFT) + 682 ((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)*step; 683 ICV_PUT_POINT(); 684 685 if( ax > ay ) 686 { 687 ptr += (pt1.x >> XY_SHIFT); 688 689 while( ecount >= 0 ) 690 { 691 tptr = ptr + (pt1.y >> XY_SHIFT) * step; 692 ICV_PUT_POINT(); 693 pt1.y += y_step; 694 ptr++; 695 ecount--; 696 } 697 } 698 else 699 { 700 ptr += (pt1.y >> XY_SHIFT) * step; 701 702 while( ecount >= 0 ) 703 { 704 tptr = ptr + (pt1.x >> XY_SHIFT); 705 ICV_PUT_POINT(); 706 pt1.x += x_step; 707 ptr += step; 708 ecount--; 709 } 710 } 711 #undef ICV_PUT_POINT 712 } 713 else 714 { 715 #define ICV_PUT_POINT() \ 716 for( j = 0; j < pix_size; j++ ) \ 717 tptr[j] = ((uchar*)color)[j]; 718 719 tptr = ptr + ((pt2.x + (XY_ONE >> 1))>> XY_SHIFT)*pix_size + 720 ((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)*step; 721 ICV_PUT_POINT(); 722 723 if( ax > ay ) 724 { 725 ptr += (pt1.x >> XY_SHIFT) * pix_size; 726 727 while( ecount >= 0 ) 728 { 729 tptr = ptr + (pt1.y >> XY_SHIFT) * step; 730 ICV_PUT_POINT(); 731 pt1.y += y_step; 732 ptr += pix_size; 733 ecount--; 734 } 735 } 736 else 737 { 738 ptr += (pt1.y >> XY_SHIFT) * step; 739 740 while( ecount >= 0 ) 741 { 742 tptr = ptr + (pt1.x >> XY_SHIFT) * pix_size; 743 ICV_PUT_POINT(); 744 pt1.x += x_step; 745 ptr += step; 746 ecount--; 747 } 748 } 749 750 #undef ICV_PUT_POINT 751 } 752} 753 754 755/****************************************************************************************\ 756* Antialiazed Elliptic Arcs via Antialiazed Lines * 757\****************************************************************************************/ 758 759static const float icvSinTable[] = 760 { 0.0000000f, 0.0174524f, 0.0348995f, 0.0523360f, 0.0697565f, 0.0871557f, 761 0.1045285f, 0.1218693f, 0.1391731f, 0.1564345f, 0.1736482f, 0.1908090f, 762 0.2079117f, 0.2249511f, 0.2419219f, 0.2588190f, 0.2756374f, 0.2923717f, 763 0.3090170f, 0.3255682f, 0.3420201f, 0.3583679f, 0.3746066f, 0.3907311f, 764 0.4067366f, 0.4226183f, 0.4383711f, 0.4539905f, 0.4694716f, 0.4848096f, 765 0.5000000f, 0.5150381f, 0.5299193f, 0.5446390f, 0.5591929f, 0.5735764f, 766 0.5877853f, 0.6018150f, 0.6156615f, 0.6293204f, 0.6427876f, 0.6560590f, 767 0.6691306f, 0.6819984f, 0.6946584f, 0.7071068f, 0.7193398f, 0.7313537f, 768 0.7431448f, 0.7547096f, 0.7660444f, 0.7771460f, 0.7880108f, 0.7986355f, 769 0.8090170f, 0.8191520f, 0.8290376f, 0.8386706f, 0.8480481f, 0.8571673f, 770 0.8660254f, 0.8746197f, 0.8829476f, 0.8910065f, 0.8987940f, 0.9063078f, 771 0.9135455f, 0.9205049f, 0.9271839f, 0.9335804f, 0.9396926f, 0.9455186f, 772 0.9510565f, 0.9563048f, 0.9612617f, 0.9659258f, 0.9702957f, 0.9743701f, 773 0.9781476f, 0.9816272f, 0.9848078f, 0.9876883f, 0.9902681f, 0.9925462f, 774 0.9945219f, 0.9961947f, 0.9975641f, 0.9986295f, 0.9993908f, 0.9998477f, 775 1.0000000f, 0.9998477f, 0.9993908f, 0.9986295f, 0.9975641f, 0.9961947f, 776 0.9945219f, 0.9925462f, 0.9902681f, 0.9876883f, 0.9848078f, 0.9816272f, 777 0.9781476f, 0.9743701f, 0.9702957f, 0.9659258f, 0.9612617f, 0.9563048f, 778 0.9510565f, 0.9455186f, 0.9396926f, 0.9335804f, 0.9271839f, 0.9205049f, 779 0.9135455f, 0.9063078f, 0.8987940f, 0.8910065f, 0.8829476f, 0.8746197f, 780 0.8660254f, 0.8571673f, 0.8480481f, 0.8386706f, 0.8290376f, 0.8191520f, 781 0.8090170f, 0.7986355f, 0.7880108f, 0.7771460f, 0.7660444f, 0.7547096f, 782 0.7431448f, 0.7313537f, 0.7193398f, 0.7071068f, 0.6946584f, 0.6819984f, 783 0.6691306f, 0.6560590f, 0.6427876f, 0.6293204f, 0.6156615f, 0.6018150f, 784 0.5877853f, 0.5735764f, 0.5591929f, 0.5446390f, 0.5299193f, 0.5150381f, 785 0.5000000f, 0.4848096f, 0.4694716f, 0.4539905f, 0.4383711f, 0.4226183f, 786 0.4067366f, 0.3907311f, 0.3746066f, 0.3583679f, 0.3420201f, 0.3255682f, 787 0.3090170f, 0.2923717f, 0.2756374f, 0.2588190f, 0.2419219f, 0.2249511f, 788 0.2079117f, 0.1908090f, 0.1736482f, 0.1564345f, 0.1391731f, 0.1218693f, 789 0.1045285f, 0.0871557f, 0.0697565f, 0.0523360f, 0.0348995f, 0.0174524f, 790 0.0000000f, -0.0174524f, -0.0348995f, -0.0523360f, -0.0697565f, -0.0871557f, 791 -0.1045285f, -0.1218693f, -0.1391731f, -0.1564345f, -0.1736482f, -0.1908090f, 792 -0.2079117f, -0.2249511f, -0.2419219f, -0.2588190f, -0.2756374f, -0.2923717f, 793 -0.3090170f, -0.3255682f, -0.3420201f, -0.3583679f, -0.3746066f, -0.3907311f, 794 -0.4067366f, -0.4226183f, -0.4383711f, -0.4539905f, -0.4694716f, -0.4848096f, 795 -0.5000000f, -0.5150381f, -0.5299193f, -0.5446390f, -0.5591929f, -0.5735764f, 796 -0.5877853f, -0.6018150f, -0.6156615f, -0.6293204f, -0.6427876f, -0.6560590f, 797 -0.6691306f, -0.6819984f, -0.6946584f, -0.7071068f, -0.7193398f, -0.7313537f, 798 -0.7431448f, -0.7547096f, -0.7660444f, -0.7771460f, -0.7880108f, -0.7986355f, 799 -0.8090170f, -0.8191520f, -0.8290376f, -0.8386706f, -0.8480481f, -0.8571673f, 800 -0.8660254f, -0.8746197f, -0.8829476f, -0.8910065f, -0.8987940f, -0.9063078f, 801 -0.9135455f, -0.9205049f, -0.9271839f, -0.9335804f, -0.9396926f, -0.9455186f, 802 -0.9510565f, -0.9563048f, -0.9612617f, -0.9659258f, -0.9702957f, -0.9743701f, 803 -0.9781476f, -0.9816272f, -0.9848078f, -0.9876883f, -0.9902681f, -0.9925462f, 804 -0.9945219f, -0.9961947f, -0.9975641f, -0.9986295f, -0.9993908f, -0.9998477f, 805 -1.0000000f, -0.9998477f, -0.9993908f, -0.9986295f, -0.9975641f, -0.9961947f, 806 -0.9945219f, -0.9925462f, -0.9902681f, -0.9876883f, -0.9848078f, -0.9816272f, 807 -0.9781476f, -0.9743701f, -0.9702957f, -0.9659258f, -0.9612617f, -0.9563048f, 808 -0.9510565f, -0.9455186f, -0.9396926f, -0.9335804f, -0.9271839f, -0.9205049f, 809 -0.9135455f, -0.9063078f, -0.8987940f, -0.8910065f, -0.8829476f, -0.8746197f, 810 -0.8660254f, -0.8571673f, -0.8480481f, -0.8386706f, -0.8290376f, -0.8191520f, 811 -0.8090170f, -0.7986355f, -0.7880108f, -0.7771460f, -0.7660444f, -0.7547096f, 812 -0.7431448f, -0.7313537f, -0.7193398f, -0.7071068f, -0.6946584f, -0.6819984f, 813 -0.6691306f, -0.6560590f, -0.6427876f, -0.6293204f, -0.6156615f, -0.6018150f, 814 -0.5877853f, -0.5735764f, -0.5591929f, -0.5446390f, -0.5299193f, -0.5150381f, 815 -0.5000000f, -0.4848096f, -0.4694716f, -0.4539905f, -0.4383711f, -0.4226183f, 816 -0.4067366f, -0.3907311f, -0.3746066f, -0.3583679f, -0.3420201f, -0.3255682f, 817 -0.3090170f, -0.2923717f, -0.2756374f, -0.2588190f, -0.2419219f, -0.2249511f, 818 -0.2079117f, -0.1908090f, -0.1736482f, -0.1564345f, -0.1391731f, -0.1218693f, 819 -0.1045285f, -0.0871557f, -0.0697565f, -0.0523360f, -0.0348995f, -0.0174524f, 820 -0.0000000f, 0.0174524f, 0.0348995f, 0.0523360f, 0.0697565f, 0.0871557f, 821 0.1045285f, 0.1218693f, 0.1391731f, 0.1564345f, 0.1736482f, 0.1908090f, 822 0.2079117f, 0.2249511f, 0.2419219f, 0.2588190f, 0.2756374f, 0.2923717f, 823 0.3090170f, 0.3255682f, 0.3420201f, 0.3583679f, 0.3746066f, 0.3907311f, 824 0.4067366f, 0.4226183f, 0.4383711f, 0.4539905f, 0.4694716f, 0.4848096f, 825 0.5000000f, 0.5150381f, 0.5299193f, 0.5446390f, 0.5591929f, 0.5735764f, 826 0.5877853f, 0.6018150f, 0.6156615f, 0.6293204f, 0.6427876f, 0.6560590f, 827 0.6691306f, 0.6819984f, 0.6946584f, 0.7071068f, 0.7193398f, 0.7313537f, 828 0.7431448f, 0.7547096f, 0.7660444f, 0.7771460f, 0.7880108f, 0.7986355f, 829 0.8090170f, 0.8191520f, 0.8290376f, 0.8386706f, 0.8480481f, 0.8571673f, 830 0.8660254f, 0.8746197f, 0.8829476f, 0.8910065f, 0.8987940f, 0.9063078f, 831 0.9135455f, 0.9205049f, 0.9271839f, 0.9335804f, 0.9396926f, 0.9455186f, 832 0.9510565f, 0.9563048f, 0.9612617f, 0.9659258f, 0.9702957f, 0.9743701f, 833 0.9781476f, 0.9816272f, 0.9848078f, 0.9876883f, 0.9902681f, 0.9925462f, 834 0.9945219f, 0.9961947f, 0.9975641f, 0.9986295f, 0.9993908f, 0.9998477f, 835 1.0000000f 836}; 837 838 839static void 840icvSinCos( int angle, float *cosval, float *sinval ) 841{ 842 angle += (angle < 0 ? 360 : 0); 843 *sinval = icvSinTable[angle]; 844 *cosval = icvSinTable[450 - angle]; 845} 846 847/* 848 constructs polygon that represents elliptic arc. 849*/ 850CV_IMPL int 851cvEllipse2Poly( CvPoint center, CvSize axes, int angle, 852 int arc_start, int arc_end, CvPoint* pts, int delta ) 853{ 854 float alpha, beta; 855 double size_a = axes.width, size_b = axes.height; 856 double cx = center.x, cy = center.y; 857 CvPoint *pts_origin = pts; 858 int i; 859 860 while( angle < 0 ) 861 angle += 360; 862 while( angle > 360 ) 863 angle -= 360; 864 865 if( arc_start > arc_end ) 866 { 867 i = arc_start; 868 arc_start = arc_end; 869 arc_end = i; 870 } 871 while( arc_start < 0 ) 872 { 873 arc_start += 360; 874 arc_end += 360; 875 } 876 while( arc_end > 360 ) 877 { 878 arc_end -= 360; 879 arc_start -= 360; 880 } 881 if( arc_end - arc_start > 360 ) 882 { 883 arc_start = 0; 884 arc_end = 360; 885 } 886 icvSinCos( angle, &alpha, &beta ); 887 888 for( i = arc_start; i < arc_end + delta; i += delta ) 889 { 890 double x, y; 891 angle = i; 892 if( angle > arc_end ) 893 angle = arc_end; 894 if( angle < 0 ) 895 angle += 360; 896 897 x = size_a * icvSinTable[450-angle]; 898 y = size_b * icvSinTable[angle]; 899 pts->x = cvRound( cx + x * alpha - y * beta ); 900 pts->y = cvRound( cy - x * beta - y * alpha ); 901 pts += i == arc_start || pts->x != pts[-1].x || pts->y != pts[-1].y; 902 } 903 904 i = (int)(pts - pts_origin); 905 for( ; i < 2; i++ ) 906 pts_origin[i] = pts_origin[i-1]; 907 return i; 908} 909 910 911static void 912icvEllipseEx( CvMat* img, CvPoint center, CvSize axes, 913 int angle, int arc_start, int arc_end, 914 const void* color, int thickness, int line_type ) 915{ 916 CvMemStorage* st = 0; 917 918 CV_FUNCNAME( "icvEllipseEx" ); 919 920 __BEGIN__; 921 922 CvPoint v[1 << 8]; 923 int count, delta; 924 925 if( axes.width < 0 || axes.height < 0 ) 926 CV_ERROR( CV_StsBadSize, "" ); 927 928 delta = (MAX(axes.width,axes.height)+(XY_ONE>>1))>>XY_SHIFT; 929 delta = delta < 3 ? 90 : delta < 10 ? 30 : delta < 15 ? 18 : 5; 930 931 count = cvEllipse2Poly( center, axes, angle, arc_start, arc_end, v, delta ); 932 933 if( thickness >= 0 ) 934 { 935 icvPolyLine( img, v, count, 0, color, thickness, line_type, XY_SHIFT ); 936 } 937 else if( arc_end - arc_start >= 360 ) 938 { 939 icvFillConvexPoly( img, v, count, color, line_type, XY_SHIFT ); 940 } 941 else 942 { 943 CvContour* edges; 944 CvSeq vtx; 945 CvSeqBlock block; 946 947 CV_CALL( st = cvCreateMemStorage( CV_DRAWING_STORAGE_BLOCK )); 948 CV_CALL( edges = (CvContour*)cvCreateSeq( 0, sizeof(CvContour), sizeof(CvPolyEdge), st )); 949 v[count++] = center; 950 951 CV_CALL( cvMakeSeqHeaderForArray( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), 952 v, count, &vtx, &block )); 953 954 CV_CALL( icvCollectPolyEdges( img, &vtx, edges, color, line_type, XY_SHIFT )); 955 CV_CALL( icvFillEdgeCollection( img, edges, color )); 956 } 957 958 __END__; 959 960 if( st ) 961 cvReleaseMemStorage( &st ); 962} 963 964 965/****************************************************************************************\ 966* Polygons filling * 967\****************************************************************************************/ 968 969/* helper macros: filling horizontal row */ 970#define ICV_HLINE( ptr, xl, xr, color, pix_size ) \ 971{ \ 972 uchar* hline_ptr = (uchar*)(ptr) + (xl)*(pix_size); \ 973 uchar* hline_max_ptr = (uchar*)(ptr) + (xr)*(pix_size); \ 974 \ 975 for( ; hline_ptr <= hline_max_ptr; hline_ptr += (pix_size))\ 976 { \ 977 int hline_j; \ 978 for( hline_j = 0; hline_j < (pix_size); hline_j++ ) \ 979 { \ 980 hline_ptr[hline_j] = ((uchar*)color)[hline_j]; \ 981 } \ 982 } \ 983} 984 985 986/* filling convex polygon. v - array of vertices, ntps - number of points */ 987static void 988icvFillConvexPoly( CvMat* img, CvPoint *v, int npts, const void* color, int line_type, int shift ) 989{ 990 struct 991 { 992 int idx, di; 993 int x, dx, ye; 994 } 995 edge[2]; 996 997 int delta = shift ? 1 << (shift - 1) : 0; 998 int i, y, imin = 0, left = 0, right = 1, x1, x2; 999 int edges = npts; 1000 int xmin, xmax, ymin, ymax; 1001 uchar* ptr = img->data.ptr; 1002 CvSize size = cvGetMatSize( img ); 1003 int pix_size = CV_ELEM_SIZE(img->type); 1004 CvPoint p0; 1005 int delta1, delta2; 1006 1007 if( line_type < CV_AA ) 1008 delta1 = delta2 = XY_ONE >> 1; 1009 //delta1 = 0, delta2 = XY_ONE - 1; 1010 else 1011 delta1 = XY_ONE - 1, delta2 = 0; 1012 1013 p0 = v[npts - 1]; 1014 p0.x <<= XY_SHIFT - shift; 1015 p0.y <<= XY_SHIFT - shift; 1016 1017 assert( 0 <= shift && shift <= XY_SHIFT ); 1018 xmin = xmax = v[0].x; 1019 ymin = ymax = v[0].y; 1020 1021 for( i = 0; i < npts; i++ ) 1022 { 1023 CvPoint p = v[i]; 1024 if( p.y < ymin ) 1025 { 1026 ymin = p.y; 1027 imin = i; 1028 } 1029 1030 ymax = MAX( ymax, p.y ); 1031 xmax = MAX( xmax, p.x ); 1032 xmin = MIN( xmin, p.x ); 1033 1034 p.x <<= XY_SHIFT - shift; 1035 p.y <<= XY_SHIFT - shift; 1036 1037 if( line_type <= 8 ) 1038 { 1039 if( shift == 0 ) 1040 { 1041 CvPoint pt0, pt1; 1042 pt0.x = p0.x >> XY_SHIFT; 1043 pt0.y = p0.y >> XY_SHIFT; 1044 pt1.x = p.x >> XY_SHIFT; 1045 pt1.y = p.y >> XY_SHIFT; 1046 icvLine( img, pt0, pt1, color, line_type ); 1047 } 1048 else 1049 icvLine2( img, p0, p, color ); 1050 } 1051 else 1052 icvLineAA( img, p0, p, color ); 1053 p0 = p; 1054 } 1055 1056 xmin = (xmin + delta) >> shift; 1057 xmax = (xmax + delta) >> shift; 1058 ymin = (ymin + delta) >> shift; 1059 ymax = (ymax + delta) >> shift; 1060 1061 if( npts < 3 || xmax < 0 || ymax < 0 || xmin >= size.width || ymin >= size.height ) 1062 return; 1063 1064 ymax = MIN( ymax, size.height - 1 ); 1065 edge[0].idx = edge[1].idx = imin; 1066 1067 edge[0].ye = edge[1].ye = y = ymin; 1068 edge[0].di = 1; 1069 edge[1].di = npts - 1; 1070 1071 ptr += img->step*y; 1072 1073 do 1074 { 1075 if( line_type < CV_AA || y < ymax || y == ymin ) 1076 { 1077 for( i = 0; i < 2; i++ ) 1078 { 1079 if( y >= edge[i].ye ) 1080 { 1081 int idx = edge[i].idx, di = edge[i].di; 1082 int xs = 0, xe, ye, ty = 0; 1083 1084 for(;;) 1085 { 1086 ty = (v[idx].y + delta) >> shift; 1087 if( ty > y || edges == 0 ) 1088 break; 1089 xs = v[idx].x; 1090 idx += di; 1091 idx -= ((idx < npts) - 1) & npts; /* idx -= idx >= npts ? npts : 0 */ 1092 edges--; 1093 } 1094 1095 ye = ty; 1096 xs <<= XY_SHIFT - shift; 1097 xe = v[idx].x << (XY_SHIFT - shift); 1098 1099 /* no more edges */ 1100 if( y >= ye ) 1101 return; 1102 1103 edge[i].ye = ye; 1104 edge[i].dx = ((xe - xs)*2 + (ye - y)) / (2 * (ye - y)); 1105 edge[i].x = xs; 1106 edge[i].idx = idx; 1107 } 1108 } 1109 } 1110 1111 if( edge[left].x > edge[right].x ) 1112 { 1113 left ^= 1; 1114 right ^= 1; 1115 } 1116 1117 x1 = edge[left].x; 1118 x2 = edge[right].x; 1119 1120 if( y >= 0 ) 1121 { 1122 int xx1 = (x1 + delta1) >> XY_SHIFT; 1123 int xx2 = (x2 + delta2) >> XY_SHIFT; 1124 1125 if( xx2 >= 0 && xx1 < size.width ) 1126 { 1127 if( xx1 < 0 ) 1128 xx1 = 0; 1129 if( xx2 >= size.width ) 1130 xx2 = size.width - 1; 1131 ICV_HLINE( ptr, xx1, xx2, color, pix_size ); 1132 } 1133 } 1134 1135 x1 += edge[left].dx; 1136 x2 += edge[right].dx; 1137 1138 edge[left].x = x1; 1139 edge[right].x = x2; 1140 ptr += img->step; 1141 } 1142 while( ++y <= ymax ); 1143} 1144 1145 1146/******** Arbitrary polygon **********/ 1147 1148static void 1149icvCollectPolyEdges( CvMat* img, CvSeq* v, CvContour* edges, 1150 const void* color, int line_type, int shift, 1151 CvPoint offset ) 1152{ 1153 int i, count = v->total; 1154 CvRect bounds = edges->rect; 1155 int delta = offset.y + (shift ? 1 << (shift - 1) : 0); 1156 int elem_type = CV_MAT_TYPE(v->flags); 1157 1158 CvSeqReader reader; 1159 CvSeqWriter writer; 1160 1161 cvStartReadSeq( v, &reader ); 1162 cvStartAppendToSeq( (CvSeq*)edges, &writer ); 1163 1164 for( i = 0; i < count; i++ ) 1165 { 1166 CvPoint pt0, pt1, t0, t1; 1167 CvPolyEdge edge; 1168 CV_READ_EDGE( pt0, pt1, reader ); 1169 1170 if( elem_type == CV_32SC2 ) 1171 { 1172 pt0.x = (pt0.x + offset.x) << (XY_SHIFT - shift); 1173 pt0.y = (pt0.y + delta) >> shift; 1174 pt1.x = (pt1.x + offset.x) << (XY_SHIFT - shift); 1175 pt1.y = (pt1.y + delta) >> shift; 1176 } 1177 else 1178 { 1179 Cv32suf x, y; 1180 assert( shift == 0 ); 1181 1182 x.i = pt0.x; y.i = pt0.y; 1183 pt0.x = cvRound((x.f + offset.x) * XY_ONE); 1184 pt0.y = cvRound(y.f + offset.y); 1185 x.i = pt1.x; y.i = pt1.y; 1186 pt1.x = cvRound((x.f + offset.x) * XY_ONE); 1187 pt1.y = cvRound(y.f + offset.y); 1188 } 1189 1190 if( line_type < CV_AA ) 1191 { 1192 t0.y = pt0.y; t1.y = pt1.y; 1193 t0.x = (pt0.x + (XY_ONE >> 1)) >> XY_SHIFT; 1194 t1.x = (pt1.x + (XY_ONE >> 1)) >> XY_SHIFT; 1195 icvLine( img, t0, t1, color, line_type ); 1196 } 1197 else 1198 { 1199 t0.x = pt0.x; t1.x = pt1.x; 1200 t0.y = pt0.y << XY_SHIFT; 1201 t1.y = pt1.y << XY_SHIFT; 1202 icvLineAA( img, t0, t1, color ); 1203 } 1204 1205 if( pt0.y == pt1.y ) 1206 continue; 1207 1208 if( pt0.y > pt1.y ) 1209 CV_SWAP( pt0, pt1, t0 ); 1210 1211 bounds.y = MIN( bounds.y, pt0.y ); 1212 bounds.height = MAX( bounds.height, pt1.y ); 1213 1214 if( pt0.x < pt1.x ) 1215 { 1216 bounds.x = MIN( bounds.x, pt0.x ); 1217 bounds.width = MAX( bounds.width, pt1.x ); 1218 } 1219 else 1220 { 1221 bounds.x = MIN( bounds.x, pt1.x ); 1222 bounds.width = MAX( bounds.width, pt0.x ); 1223 } 1224 1225 edge.y0 = pt0.y; 1226 edge.y1 = pt1.y; 1227 edge.x = pt0.x; 1228 edge.dx = (pt1.x - pt0.x) / (pt1.y - pt0.y); 1229 assert( edge.y0 < edge.y1 ); 1230 1231 CV_WRITE_SEQ_ELEM( edge, writer ); 1232 } 1233 1234 edges->rect = bounds; 1235 cvEndWriteSeq( &writer ); 1236} 1237 1238static int 1239icvCmpEdges( const void* _e1, const void* _e2, void* /*userdata*/ ) 1240{ 1241 CvPolyEdge *e1 = (CvPolyEdge*)_e1, *e2 = (CvPolyEdge*)_e2; 1242 return e1->y0 - e2->y0 ? e1->y0 - e2->y0 : 1243 e1->x - e2->x ? e1->x - e2->x : e1->dx - e2->dx; 1244} 1245 1246/**************** helper macros and functions for sequence/contour processing ***********/ 1247 1248static void 1249icvFillEdgeCollection( CvMat* img, CvContour* edges, const void* color ) 1250{ 1251 CvPolyEdge tmp; 1252 int i, y, total = edges->total; 1253 CvSeqReader reader; 1254 CvSize size = cvGetMatSize(img); 1255 CvPolyEdge* e; 1256 int y_max = INT_MIN; 1257 int pix_size = CV_ELEM_SIZE(img->type); 1258 1259 __BEGIN__; 1260 1261 memset( &tmp, 0, sizeof(tmp)); 1262 1263 /* check parameters */ 1264 if( edges->total < 2 || edges->rect.height < 0 || edges->rect.y >= size.height || 1265 edges->rect.width < 0 || edges->rect.x >= size.width ) 1266 EXIT; 1267 1268 cvSeqSort( (CvSeq*)edges, icvCmpEdges, 0 ); 1269 cvStartReadSeq( (CvSeq*)edges, &reader ); 1270 1271#ifdef _DEBUG 1272 e = &tmp; 1273 tmp.y0 = INT_MIN; 1274#endif 1275 1276 for( i = 0; i < total; i++ ) 1277 { 1278 CvPolyEdge* e1 = (CvPolyEdge*)(reader.ptr); 1279 1280#ifdef _DEBUG 1281 assert( e1->y0 < e1->y1 && (i == 0 || icvCmpEdges( e, e1, 0 ) <= 0) ); 1282 e = e1; 1283#endif 1284 y_max = MAX( y_max, e1->y1 ); 1285 1286 CV_NEXT_SEQ_ELEM( sizeof(CvPolyEdge), reader ); 1287 } 1288 1289 /* start drawing */ 1290 tmp.y0 = INT_MAX; 1291 cvSeqPush( (CvSeq*)edges, &tmp ); 1292 1293 i = 0; 1294 tmp.next = 0; 1295 cvStartReadSeq( (CvSeq*)edges, &reader ); 1296 e = (CvPolyEdge*)(reader.ptr); 1297 y_max = MIN( y_max, size.height ); 1298 1299 for( y = e->y0; y < y_max; y++ ) 1300 { 1301 CvPolyEdge *last, *prelast, *keep_prelast; 1302 int sort_flag = 0; 1303 int draw = 0; 1304 int clipline = y < 0; 1305 1306 prelast = &tmp; 1307 last = tmp.next; 1308 while( last || e->y0 == y ) 1309 { 1310 if( last && last->y1 == y ) 1311 { 1312 /* exlude edge if y reachs its lower point */ 1313 prelast->next = last->next; 1314 last = last->next; 1315 continue; 1316 } 1317 keep_prelast = prelast; 1318 if( last && (e->y0 > y || last->x < e->x) ) 1319 { 1320 /* go to the next edge in active list */ 1321 prelast = last; 1322 last = last->next; 1323 } 1324 else if( i < total ) 1325 { 1326 /* insert new edge into active list if y reachs its upper point */ 1327 prelast->next = e; 1328 e->next = last; 1329 prelast = e; 1330 CV_NEXT_SEQ_ELEM( edges->elem_size, reader ); 1331 e = (CvPolyEdge*)(reader.ptr); 1332 i++; 1333 } 1334 else 1335 break; 1336 1337 if( draw ) 1338 { 1339 if( !clipline ) 1340 { 1341 /* convert x's from fixed-point to image coordinates */ 1342 uchar *timg = (uchar*)(img->data.ptr) + y * img->step; 1343 int x1 = keep_prelast->x; 1344 int x2 = prelast->x; 1345 1346 if( x1 > x2 ) 1347 { 1348 int t = x1; 1349 1350 x1 = x2; 1351 x2 = t; 1352 } 1353 1354 x1 = (x1 + XY_ONE - 1) >> XY_SHIFT; 1355 x2 = x2 >> XY_SHIFT; 1356 1357 /* clip and draw the line */ 1358 if( x1 < size.width && x2 >= 0 ) 1359 { 1360 if( x1 < 0 ) 1361 x1 = 0; 1362 if( x2 >= size.width ) 1363 x2 = size.width - 1; 1364 ICV_HLINE( timg, x1, x2, color, pix_size ); 1365 } 1366 } 1367 keep_prelast->x += keep_prelast->dx; 1368 prelast->x += prelast->dx; 1369 } 1370 draw ^= 1; 1371 } 1372 1373 /* sort edges (bubble sort on list) */ 1374 keep_prelast = 0; 1375 1376 do 1377 { 1378 prelast = &tmp; 1379 last = tmp.next; 1380 1381 while( last != keep_prelast && last->next != 0 ) 1382 { 1383 CvPolyEdge *te = last->next; 1384 1385 /* swap edges */ 1386 if( last->x > te->x ) 1387 { 1388 prelast->next = te; 1389 last->next = te->next; 1390 te->next = last; 1391 prelast = te; 1392 sort_flag = 1; 1393 } 1394 else 1395 { 1396 prelast = last; 1397 last = te; 1398 } 1399 } 1400 keep_prelast = prelast; 1401 } 1402 while( sort_flag && keep_prelast != tmp.next && keep_prelast != &tmp ); 1403 } 1404 1405 __END__; 1406} 1407 1408 1409/* draws simple or filled circle */ 1410static void 1411icvCircle( CvMat* img, CvPoint center, int radius, const void* color, int fill ) 1412{ 1413 CvSize size = cvGetMatSize( img ); 1414 int step = img->step; 1415 int pix_size = CV_ELEM_SIZE(img->type); 1416 uchar* ptr = (uchar*)(img->data.ptr); 1417 int err = 0, dx = radius, dy = 0, plus = 1, minus = (radius << 1) - 1; 1418 int inside = center.x >= radius && center.x < size.width - radius && 1419 center.y >= radius && center.y < size.height - radius; 1420 1421 #define ICV_PUT_POINT( ptr, x ) \ 1422 CV_MEMCPY_CHAR( ptr + (x)*pix_size, color, pix_size ); 1423 1424 while( dx >= dy ) 1425 { 1426 int mask; 1427 int y11 = center.y - dy, y12 = center.y + dy, y21 = center.y - dx, y22 = center.y + dx; 1428 int x11 = center.x - dx, x12 = center.x + dx, x21 = center.x - dy, x22 = center.x + dy; 1429 1430 if( inside ) 1431 { 1432 uchar *tptr0 = ptr + y11 * step; 1433 uchar *tptr1 = ptr + y12 * step; 1434 1435 if( !fill ) 1436 { 1437 ICV_PUT_POINT( tptr0, x11 ); 1438 ICV_PUT_POINT( tptr1, x11 ); 1439 ICV_PUT_POINT( tptr0, x12 ); 1440 ICV_PUT_POINT( tptr1, x12 ); 1441 } 1442 else 1443 { 1444 ICV_HLINE( tptr0, x11, x12, color, pix_size ); 1445 ICV_HLINE( tptr1, x11, x12, color, pix_size ); 1446 } 1447 1448 tptr0 = ptr + y21 * step; 1449 tptr1 = ptr + y22 * step; 1450 1451 if( !fill ) 1452 { 1453 ICV_PUT_POINT( tptr0, x21 ); 1454 ICV_PUT_POINT( tptr1, x21 ); 1455 ICV_PUT_POINT( tptr0, x22 ); 1456 ICV_PUT_POINT( tptr1, x22 ); 1457 } 1458 else 1459 { 1460 ICV_HLINE( tptr0, x21, x22, color, pix_size ); 1461 ICV_HLINE( tptr1, x21, x22, color, pix_size ); 1462 } 1463 } 1464 else if( x11 < size.width && x12 >= 0 && y21 < size.height && y22 >= 0 ) 1465 { 1466 if( fill ) 1467 { 1468 x11 = MAX( x11, 0 ); 1469 x12 = MIN( x12, size.width - 1 ); 1470 } 1471 1472 if( (unsigned)y11 < (unsigned)size.height ) 1473 { 1474 uchar *tptr = ptr + y11 * step; 1475 1476 if( !fill ) 1477 { 1478 if( x11 >= 0 ) 1479 ICV_PUT_POINT( tptr, x11 ); 1480 if( x12 < size.width ) 1481 ICV_PUT_POINT( tptr, x12 ); 1482 } 1483 else 1484 ICV_HLINE( tptr, x11, x12, color, pix_size ); 1485 } 1486 1487 if( (unsigned)y12 < (unsigned)size.height ) 1488 { 1489 uchar *tptr = ptr + y12 * step; 1490 1491 if( !fill ) 1492 { 1493 if( x11 >= 0 ) 1494 ICV_PUT_POINT( tptr, x11 ); 1495 if( x12 < size.width ) 1496 ICV_PUT_POINT( tptr, x12 ); 1497 } 1498 else 1499 ICV_HLINE( tptr, x11, x12, color, pix_size ); 1500 } 1501 1502 if( x21 < size.width && x22 >= 0 ) 1503 { 1504 if( fill ) 1505 { 1506 x21 = MAX( x21, 0 ); 1507 x22 = MIN( x22, size.width - 1 ); 1508 } 1509 1510 if( (unsigned)y21 < (unsigned)size.height ) 1511 { 1512 uchar *tptr = ptr + y21 * step; 1513 1514 if( !fill ) 1515 { 1516 if( x21 >= 0 ) 1517 ICV_PUT_POINT( tptr, x21 ); 1518 if( x22 < size.width ) 1519 ICV_PUT_POINT( tptr, x22 ); 1520 } 1521 else 1522 ICV_HLINE( tptr, x21, x22, color, pix_size ); 1523 } 1524 1525 if( (unsigned)y22 < (unsigned)size.height ) 1526 { 1527 uchar *tptr = ptr + y22 * step; 1528 1529 if( !fill ) 1530 { 1531 if( x21 >= 0 ) 1532 ICV_PUT_POINT( tptr, x21 ); 1533 if( x22 < size.width ) 1534 ICV_PUT_POINT( tptr, x22 ); 1535 } 1536 else 1537 ICV_HLINE( tptr, x21, x22, color, pix_size ); 1538 } 1539 } 1540 } 1541 dy++; 1542 err += plus; 1543 plus += 2; 1544 1545 mask = (err <= 0) - 1; 1546 1547 err -= minus & mask; 1548 dx += mask; 1549 minus -= mask & 2; 1550 } 1551 1552 #undef ICV_PUT_POINT 1553} 1554 1555 1556static void 1557icvThickLine( CvMat* img, CvPoint p0, CvPoint p1, const void* color, 1558 int thickness, int line_type, int flags, int shift ) 1559{ 1560 static const double INV_XY_ONE = 1./XY_ONE; 1561 1562 p0.x <<= XY_SHIFT - shift; 1563 p0.y <<= XY_SHIFT - shift; 1564 p1.x <<= XY_SHIFT - shift; 1565 p1.y <<= XY_SHIFT - shift; 1566 1567 if( thickness <= 1 ) 1568 { 1569 if( line_type < CV_AA ) 1570 { 1571 if( line_type == 1 || line_type == 4 || shift == 0 ) 1572 { 1573 p0.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT; 1574 p0.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT; 1575 p1.x = (p1.x + (XY_ONE>>1)) >> XY_SHIFT; 1576 p1.y = (p1.y + (XY_ONE>>1)) >> XY_SHIFT; 1577 icvLine( img, p0, p1, color, line_type ); 1578 } 1579 else 1580 icvLine2( img, p0, p1, color ); 1581 } 1582 else 1583 icvLineAA( img, p0, p1, color ); 1584 } 1585 else 1586 { 1587 CvPoint pt[4], dp = {0,0}; 1588 double dx = (p0.x - p1.x)*INV_XY_ONE, dy = (p1.y - p0.y)*INV_XY_ONE; 1589 double r = dx * dx + dy * dy; 1590 int i; 1591 thickness <<= XY_SHIFT - 1; 1592 1593 if( fabs(r) > DBL_EPSILON ) 1594 { 1595 r = thickness * cvInvSqrt( (float) r ); 1596 dp.x = cvRound( dy * r ); 1597 dp.y = cvRound( dx * r ); 1598 } 1599 1600 pt[0].x = p0.x + dp.x; 1601 pt[0].y = p0.y + dp.y; 1602 pt[1].x = p0.x - dp.x; 1603 pt[1].y = p0.y - dp.y; 1604 pt[2].x = p1.x - dp.x; 1605 pt[2].y = p1.y - dp.y; 1606 pt[3].x = p1.x + dp.x; 1607 pt[3].y = p1.y + dp.y; 1608 1609 icvFillConvexPoly( img, pt, 4, color, line_type, XY_SHIFT ); 1610 1611 for( i = 0; i < 2; i++ ) 1612 { 1613 if( flags & (i+1) ) 1614 { 1615 if( line_type < CV_AA ) 1616 { 1617 CvPoint center; 1618 center.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT; 1619 center.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT; 1620 icvCircle( img, center, thickness >> XY_SHIFT, color, 1 ); 1621 } 1622 else 1623 { 1624 icvEllipseEx( img, p0, cvSize(thickness, thickness), 1625 0, 0, 360, color, -1, line_type ); 1626 } 1627 } 1628 p0 = p1; 1629 } 1630 } 1631} 1632 1633 1634static void 1635icvPolyLine( CvMat* img, CvPoint *v, int count, int is_closed, 1636 const void* color, int thickness, 1637 int line_type, int shift ) 1638{ 1639 CV_FUNCNAME("icvPolyLine"); 1640 1641 __BEGIN__; 1642 1643 if( count > 0 ) 1644 { 1645 int i = is_closed ? count - 1 : 0; 1646 int flags = 2 + !is_closed; 1647 CvPoint p0; 1648 assert( 0 <= shift && shift <= XY_SHIFT ); 1649 assert( img && thickness >= 0 ); 1650 assert( v && count >= 0 ); 1651 1652 if( !v ) 1653 CV_ERROR( CV_StsNullPtr, "" ); 1654 1655 p0 = v[i]; 1656 for( i = !is_closed; i < count; i++ ) 1657 { 1658 CvPoint p = v[i]; 1659 icvThickLine( img, p0, p, color, thickness, line_type, flags, shift ); 1660 p0 = p; 1661 flags = 2; 1662 } 1663 } 1664 1665 __END__; 1666} 1667 1668/****************************************************************************************\ 1669* External functions * 1670\****************************************************************************************/ 1671 1672CV_IMPL CvScalar cvColorToScalar( double packed_color, int type ) 1673{ 1674 CvScalar scalar; 1675 1676 if( CV_MAT_DEPTH( type ) == CV_8U ) 1677 { 1678 int icolor = cvRound( packed_color ); 1679 if( CV_MAT_CN( type ) > 1 ) 1680 { 1681 scalar.val[0] = icolor & 255; 1682 scalar.val[1] = (icolor >> 8) & 255; 1683 scalar.val[2] = (icolor >> 16) & 255; 1684 scalar.val[3] = (icolor >> 24) & 255; 1685 } 1686 else 1687 { 1688 scalar.val[0] = CV_CAST_8U( icolor ); 1689 scalar.val[1] = scalar.val[2] = scalar.val[3] = 0; 1690 } 1691 } 1692 else if( CV_MAT_DEPTH( type ) == CV_8S ) 1693 { 1694 int icolor = cvRound( packed_color ); 1695 if( CV_MAT_CN( type ) > 1 ) 1696 { 1697 scalar.val[0] = (char)icolor; 1698 scalar.val[1] = (char)(icolor >> 8); 1699 scalar.val[2] = (char)(icolor >> 16); 1700 scalar.val[3] = (char)(icolor >> 24); 1701 } 1702 else 1703 { 1704 scalar.val[0] = CV_CAST_8S( icolor ); 1705 scalar.val[1] = scalar.val[2] = scalar.val[3] = 0; 1706 } 1707 } 1708 else 1709 { 1710 int cn = CV_MAT_CN( type ); 1711 switch( cn ) 1712 { 1713 case 1: 1714 scalar.val[0] = packed_color; 1715 scalar.val[1] = scalar.val[2] = scalar.val[3] = 0; 1716 break; 1717 case 2: 1718 scalar.val[0] = scalar.val[1] = packed_color; 1719 scalar.val[2] = scalar.val[3] = 0; 1720 break; 1721 case 3: 1722 scalar.val[0] = scalar.val[1] = scalar.val[2] = packed_color; 1723 scalar.val[3] = 0; 1724 break; 1725 default: 1726 scalar.val[0] = scalar.val[1] = 1727 scalar.val[2] = scalar.val[3] = packed_color; 1728 break; 1729 } 1730 } 1731 1732 return scalar; 1733} 1734 1735 1736CV_IMPL void 1737cvLine( void* img, CvPoint pt1, CvPoint pt2, CvScalar color, 1738 int thickness, int line_type, int shift ) 1739{ 1740 CV_FUNCNAME( "cvLine" ); 1741 1742 __BEGIN__; 1743 1744 int coi = 0; 1745 CvMat stub, *mat = (CvMat*)img; 1746 double buf[4]; 1747 1748 CV_CALL( mat = cvGetMat( img, &stub, &coi )); 1749 1750 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U ) 1751 line_type = 8; 1752 1753 if( coi != 0 ) 1754 CV_ERROR( CV_BadCOI, cvUnsupportedFormat ); 1755 1756 if( (unsigned)thickness > 255 ) 1757 CV_ERROR( CV_StsOutOfRange, "" ); 1758 1759 if( shift < 0 || XY_SHIFT < shift ) 1760 CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" ); 1761 1762 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 )); 1763 icvThickLine( mat, pt1, pt2, buf, thickness, line_type, 3, shift ); 1764 1765 __END__; 1766} 1767 1768 1769CV_IMPL void 1770cvRectangle( void* img, CvPoint pt1, CvPoint pt2, 1771 CvScalar color, int thickness, 1772 int line_type, int shift ) 1773{ 1774 CvPoint pt[4]; 1775 1776 CV_FUNCNAME("cvRectangle"); 1777 1778 __BEGIN__; 1779 1780 int coi = 0; 1781 CvMat stub, *mat = (CvMat*)img; 1782 double buf[4]; 1783 1784 if( thickness > 255 ) 1785 CV_ERROR( CV_StsOutOfRange, "" ); 1786 1787 CV_CALL( mat = cvGetMat( img, &stub, &coi )); 1788 1789 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U ) 1790 line_type = 8; 1791 1792 if( coi != 0 ) 1793 CV_ERROR( CV_BadCOI, cvUnsupportedFormat ); 1794 1795 if( shift < 0 || XY_SHIFT < shift ) 1796 CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" ); 1797 1798 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 )); 1799 1800 pt[0] = pt1; 1801 pt[1].x = pt2.x; 1802 pt[1].y = pt1.y; 1803 pt[2] = pt2; 1804 pt[3].x = pt1.x; 1805 pt[3].y = pt2.y; 1806 1807 if( thickness >= 0 ) 1808 icvPolyLine( mat, pt, 4, 1, buf, thickness, line_type, shift ); 1809 else 1810 icvFillConvexPoly( mat, pt, 4, buf, line_type, shift ); 1811 1812 __END__; 1813} 1814 1815 1816CV_IMPL void 1817cvCircle( void *img, CvPoint center, int radius, 1818 CvScalar color, int thickness, int line_type, int shift ) 1819{ 1820 CV_FUNCNAME( "cvCircle" ); 1821 1822 __BEGIN__; 1823 1824 int coi = 0; 1825 CvMat stub, *mat = (CvMat*)img; 1826 double buf[4]; 1827 1828 CV_CALL( mat = cvGetMat( mat, &stub, &coi )); 1829 1830 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U ) 1831 line_type = 8; 1832 1833 if( coi != 0 ) 1834 CV_ERROR( CV_BadCOI, cvUnsupportedFormat ); 1835 1836 if( radius < 0 ) 1837 CV_ERROR( CV_StsOutOfRange, "" ); 1838 1839 if( thickness > 255 ) 1840 CV_ERROR( CV_StsOutOfRange, "" ); 1841 1842 if( shift < 0 || XY_SHIFT < shift ) 1843 CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" ); 1844 1845 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 )); 1846 1847 if( thickness > 1 || line_type >= CV_AA ) 1848 { 1849 center.x <<= XY_SHIFT - shift; 1850 center.y <<= XY_SHIFT - shift; 1851 radius <<= XY_SHIFT - shift; 1852 icvEllipseEx( mat, center, cvSize( radius, radius ), 1853 0, 0, 360, buf, thickness, line_type ); 1854 } 1855 else 1856 { 1857 icvCircle( mat, center, radius, buf, thickness < 0 ); 1858 } 1859 1860 __END__; 1861} 1862 1863 1864CV_IMPL void 1865cvEllipse( void *img, CvPoint center, CvSize axes, 1866 double angle, double start_angle, double end_angle, 1867 CvScalar color, int thickness, int line_type, int shift ) 1868{ 1869 CV_FUNCNAME( "cvEllipse" ); 1870 1871 __BEGIN__; 1872 1873 int coi = 0; 1874 CvMat stub, *mat = (CvMat*)img; 1875 double buf[4]; 1876 1877 CV_CALL( mat = cvGetMat( mat, &stub, &coi )); 1878 1879 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U ) 1880 line_type = 8; 1881 1882 if( coi != 0 ) 1883 CV_ERROR( CV_BadCOI, cvUnsupportedFormat ); 1884 1885 if( axes.width < 0 || axes.height < 0 ) 1886 CV_ERROR( CV_StsOutOfRange, "" ); 1887 1888 if( thickness > 255 ) 1889 CV_ERROR( CV_StsOutOfRange, "" ); 1890 1891 if( shift < 0 || XY_SHIFT < shift ) 1892 CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" ); 1893 1894 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 )); 1895 1896 { 1897 int _angle = cvRound(angle); 1898 int _start_angle = cvRound(start_angle); 1899 int _end_angle = cvRound(end_angle); 1900 center.x <<= XY_SHIFT - shift; 1901 center.y <<= XY_SHIFT - shift; 1902 axes.width <<= XY_SHIFT - shift; 1903 axes.height <<= XY_SHIFT - shift; 1904 1905 CV_CALL( icvEllipseEx( mat, center, axes, _angle, _start_angle, 1906 _end_angle, buf, thickness, line_type )); 1907 } 1908 1909 __END__; 1910} 1911 1912 1913CV_IMPL void 1914cvFillConvexPoly( void *img, CvPoint *pts, int npts, CvScalar color, int line_type, int shift ) 1915{ 1916 CV_FUNCNAME( "cvFillConvexPoly" ); 1917 1918 __BEGIN__; 1919 1920 int coi = 0; 1921 CvMat stub, *mat = (CvMat*)img; 1922 double buf[4]; 1923 1924 CV_CALL( mat = cvGetMat( mat, &stub, &coi )); 1925 1926 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U ) 1927 line_type = 8; 1928 1929 if( coi != 0 ) 1930 CV_ERROR( CV_BadCOI, cvUnsupportedFormat ); 1931 1932 if( !pts ) 1933 CV_ERROR( CV_StsNullPtr, "" ); 1934 1935 if( npts <= 0 ) 1936 CV_ERROR( CV_StsOutOfRange, "" ); 1937 1938 if( shift < 0 || XY_SHIFT < shift ) 1939 CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" ); 1940 1941 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 )); 1942 icvFillConvexPoly( mat, pts, npts, buf, line_type, shift ); 1943 1944 __END__; 1945} 1946 1947 1948CV_IMPL void 1949cvFillPoly( void *img, CvPoint **pts, int *npts, int contours, 1950 CvScalar color, int line_type, int shift ) 1951{ 1952 CvMemStorage* st = 0; 1953 1954 CV_FUNCNAME( "cvFillPoly" ); 1955 1956 __BEGIN__; 1957 1958 int coi = 0; 1959 CvMat stub, *mat = (CvMat*)img; 1960 double buf[4]; 1961 1962 CV_CALL( mat = cvGetMat( mat, &stub, &coi )); 1963 1964 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U ) 1965 line_type = 8; 1966 1967 if( coi != 0 ) 1968 CV_ERROR( CV_BadCOI, cvUnsupportedFormat ); 1969 1970 if( contours <= 0 ) 1971 CV_ERROR( CV_StsBadArg, "" ); 1972 1973 if( !pts ) 1974 CV_ERROR( CV_StsNullPtr, "" ); 1975 1976 if( npts <= 0 ) 1977 CV_ERROR( CV_StsNullPtr, "" ); 1978 1979 if( shift < 0 || XY_SHIFT < shift ) 1980 CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" ); 1981 1982 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 )); 1983 1984 { 1985 CvContour* edges = 0; 1986 CvSeq vtx; 1987 CvSeqBlock block; 1988 1989 CV_CALL( st = cvCreateMemStorage( CV_DRAWING_STORAGE_BLOCK )); 1990 CV_CALL( edges = (CvContour*)cvCreateSeq( 0, sizeof(CvContour), 1991 sizeof(CvPolyEdge), st )); 1992 1993 for( int i = 0; i < contours; i++ ) 1994 { 1995 if( !pts[i] ) 1996 CV_ERROR( CV_StsNullPtr, "" ); 1997 1998 if( npts[i] < 0 ) 1999 CV_ERROR( CV_StsOutOfRange, "" ); 2000 2001 cvMakeSeqHeaderForArray( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), 2002 pts[i], npts[i], &vtx, &block ); 2003 2004 CV_CALL( icvCollectPolyEdges( mat, &vtx, edges, buf, line_type, shift )); 2005 } 2006 2007 CV_CALL( icvFillEdgeCollection( mat, edges, buf )); 2008 } 2009 2010 __END__; 2011 2012 cvReleaseMemStorage( &st ); 2013} 2014 2015 2016 2017CV_IMPL void 2018cvPolyLine( void *img, CvPoint **pts, int *npts, 2019 int contours, int closed, CvScalar color, 2020 int thickness, int line_type, int shift ) 2021{ 2022 CV_FUNCNAME( "cvPolyLine" ); 2023 2024 __BEGIN__; 2025 2026 int coi = 0, i; 2027 CvMat stub, *mat = (CvMat*)img; 2028 double buf[4]; 2029 2030 CV_CALL( mat = cvGetMat( mat, &stub, &coi )); 2031 2032 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U ) 2033 line_type = 8; 2034 2035 if( coi != 0 ) 2036 CV_ERROR( CV_BadCOI, cvUnsupportedFormat ); 2037 2038 if( contours <= 0 ) 2039 CV_ERROR( CV_StsBadArg, "" ); 2040 2041 if( thickness < -1 || thickness > 255 ) 2042 CV_ERROR( CV_StsBadArg, "" ); 2043 2044 if( !pts ) 2045 CV_ERROR( CV_StsNullPtr, "" ); 2046 2047 if( npts <= 0 ) 2048 CV_ERROR( CV_StsNullPtr, "" ); 2049 2050 if( shift < 0 || XY_SHIFT < shift ) 2051 CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" ); 2052 2053 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 )); 2054 2055 for( i = 0; i < contours; i++ ) 2056 icvPolyLine( mat, pts[i], npts[i], closed, buf, thickness, line_type, shift ); 2057 2058 __END__; 2059} 2060 2061 2062#define CV_FONT_SIZE_SHIFT 8 2063#define CV_FONT_ITALIC_ALPHA (1 << 8) 2064#define CV_FONT_ITALIC_DIGIT (2 << 8) 2065#define CV_FONT_ITALIC_PUNCT (4 << 8) 2066#define CV_FONT_ITALIC_BRACES (8 << 8) 2067#define CV_FONT_HAVE_GREEK (16 << 8) 2068#define CV_FONT_HAVE_CYRILLIC (32 << 8) 2069 2070static const int icvHersheyPlain[] = { 2071(5 + 4*16) + CV_FONT_HAVE_GREEK, 2072199, 214, 217, 233, 219, 197, 234, 216, 221, 222, 228, 225, 211, 224, 210, 220, 2073200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 212, 213, 191, 226, 192, 2074215, 190, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 207514, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 193, 84, 2076194, 85, 86, 87, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 2077112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 2078195, 223, 196, 88 }; 2079 2080static const int icvHersheyPlainItalic[] = { 2081(5 + 4*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_HAVE_GREEK, 2082199, 214, 217, 233, 219, 197, 234, 216, 221, 222, 228, 225, 211, 224, 210, 220, 2083200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 212, 213, 191, 226, 192, 2084215, 190, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 208564, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 193, 84, 2086194, 85, 86, 87, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 2087162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 2088195, 223, 196, 88 }; 2089 2090static const int icvHersheyComplexSmall[] = { 2091(6 + 7*16) + CV_FONT_HAVE_GREEK, 20921199, 1214, 1217, 1275, 1274, 1271, 1272, 1216, 1221, 1222, 1219, 1232, 1211, 1231, 1210, 1220, 20931200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1212, 2213, 1241, 1238, 1242, 20941215, 1273, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 20951014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1223, 1084, 20961224, 1247, 586, 1249, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 20971112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 20981225, 1229, 1226, 1246 }; 2099 2100static const int icvHersheyComplexSmallItalic[] = { 2101(6 + 7*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_HAVE_GREEK, 21021199, 1214, 1217, 1275, 1274, 1271, 1272, 1216, 1221, 1222, 1219, 1232, 1211, 1231, 1210, 1220, 21031200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1212, 1213, 1241, 1238, 1242, 21041215, 1273, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 21051064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1223, 1084, 21061224, 1247, 586, 1249, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 21071162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 21081225, 1229, 1226, 1246 }; 2109 2110static const int icvHersheySimplex[] = { 2111(9 + 12*16) + CV_FONT_HAVE_GREEK, 21122199, 714, 717, 733, 719, 697, 734, 716, 721, 722, 728, 725, 711, 724, 710, 720, 2113700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 712, 713, 691, 726, 692, 2114715, 690, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 2115514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 693, 584, 2116694, 2247, 586, 2249, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 2117612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 2118695, 723, 696, 2246 }; 2119 2120static const int icvHersheyDuplex[] = { 2121(9 + 12*16) + CV_FONT_HAVE_GREEK, 21222199, 2714, 2728, 2732, 2719, 2733, 2718, 2727, 2721, 2722, 2723, 2725, 2711, 2724, 2710, 2720, 21232700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2712, 2713, 2730, 2726, 2731, 21242715, 2734, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, 21252514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2223, 2084, 21262224, 2247, 587, 2249, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 21272612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 21282225, 2229, 2226, 2246 }; 2129 2130static const int icvHersheyComplex[] = { 2131(9 + 12*16) + CV_FONT_HAVE_GREEK + CV_FONT_HAVE_CYRILLIC, 21322199, 2214, 2217, 2275, 2274, 2271, 2272, 2216, 2221, 2222, 2219, 2232, 2211, 2231, 2210, 2220, 21332200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2212, 2213, 2241, 2238, 2242, 21342215, 2273, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 21352014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2223, 2084, 21362224, 2247, 587, 2249, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 21372112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 21382225, 2229, 2226, 2246 }; 2139 2140static const int icvHersheyComplexItalic[] = { 2141(9 + 12*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_ITALIC_DIGIT + CV_FONT_ITALIC_PUNCT + 2142CV_FONT_HAVE_GREEK + CV_FONT_HAVE_CYRILLIC, 21432199, 2764, 2778, 2782, 2769, 2783, 2768, 2777, 2771, 2772, 2219, 2232, 2211, 2231, 2210, 2220, 21442750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2212, 2213, 2241, 2238, 2242, 21452765, 2273, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 21462064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2223, 2084, 21472224, 2247, 587, 2249, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 21482162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 21492225, 2229, 2226, 2246 }; 2150 2151static const int icvHersheyTriplex[] = { 2152(9 + 12*16) + CV_FONT_HAVE_GREEK, 21532199, 3214, 3228, 3232, 3219, 3233, 3218, 3227, 3221, 3222, 3223, 3225, 3211, 3224, 3210, 3220, 21543200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3212, 3213, 3230, 3226, 3231, 21553215, 3234, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, 21562014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 2223, 2084, 21572224, 2247, 587, 2249, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111, 21583112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, 21592225, 2229, 2226, 2246 }; 2160 2161static const int icvHersheyTriplexItalic[] = { 2162(9 + 12*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_ITALIC_DIGIT + 2163CV_FONT_ITALIC_PUNCT + CV_FONT_HAVE_GREEK, 21642199, 3264, 3278, 3282, 3269, 3233, 3268, 3277, 3271, 3272, 3223, 3225, 3261, 3224, 3260, 3270, 21653250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3262, 3263, 3230, 3226, 3231, 21663265, 3234, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063, 21672064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 2223, 2084, 21682224, 2247, 587, 2249, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161, 21693162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176, 21702225, 2229, 2226, 2246 }; 2171 2172static const int icvHersheyScriptSimplex[] = { 2173(9 + 12*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_HAVE_GREEK, 21742199, 714, 717, 733, 719, 697, 734, 716, 721, 722, 728, 725, 711, 724, 710, 720, 2175700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 712, 713, 691, 726, 692, 2176715, 690, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 2177564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 693, 584, 2178694, 2247, 586, 2249, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 2179662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 2180695, 723, 696, 2246 }; 2181 2182static const int icvHersheyScriptComplex[] = { 2183(9 + 12*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_ITALIC_DIGIT + CV_FONT_ITALIC_PUNCT + CV_FONT_HAVE_GREEK, 21842199, 2764, 2778, 2782, 2769, 2783, 2768, 2777, 2771, 2772, 2219, 2232, 2211, 2231, 2210, 2220, 21852750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2212, 2213, 2241, 2238, 2242, 21862215, 2273, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562, 2563, 21872564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2223, 2084, 21882224, 2247, 586, 2249, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, 21892662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 21902225, 2229, 2226, 2246 }; 2191 2192 2193CV_IMPL void 2194cvPutText( void *img, const char *text, CvPoint org, const CvFont *font, CvScalar color ) 2195{ 2196 CV_FUNCNAME( "cvPutText" ); 2197 2198 __BEGIN__; 2199 2200 int view_x, view_y; 2201 int coi = 0; 2202 int top_bottom = 0, base_line; 2203 int hscale, vscale, default_shear, italic_shear; 2204 int thickness, line_type; 2205 CvMat stub, *mat = (CvMat*)img; 2206 double buf[4]; 2207 CvPoint pt[1 << 10]; 2208 int count; 2209 2210 int i; 2211 const char **faces = icvHersheyGlyphs; 2212 2213 CV_CALL( mat = cvGetMat( mat, &stub, &coi )); 2214 2215 if( coi != 0 ) 2216 CV_ERROR( CV_BadCOI, cvUnsupportedFormat ); 2217 2218 if( CV_IS_IMAGE_HDR(img) && ((IplImage*)img)->origin ) 2219 top_bottom = 1; 2220 2221 if( !text || !font || !font->ascii ) 2222 CV_ERROR( CV_StsNullPtr, "" ); 2223 2224 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 )); 2225 base_line = -(font->ascii[0] & 15); 2226 hscale = cvRound(font->hscale*XY_ONE); 2227 vscale = cvRound(font->vscale*XY_ONE); 2228 default_shear = cvRound(font->shear*font->vscale*XY_ONE); 2229 italic_shear = !(font->font_face & CV_FONT_ITALIC) ? 0 : cvRound(font->vscale*.25*XY_ONE); 2230 thickness = font->thickness; 2231 line_type = font->line_type; 2232 2233 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U ) 2234 line_type = 8; 2235 2236 if( top_bottom ) 2237 vscale = -vscale; 2238 2239 view_x = org.x << XY_SHIFT; 2240 view_y = (org.y << XY_SHIFT) + base_line*vscale; 2241 2242 for( i = 0; text[i] != '\0'; i++ ) 2243 { 2244 int c = (uchar)text[i]; 2245 int dx, shear = default_shear; 2246 const char* ptr; 2247 CvPoint p; 2248 2249 if( c > 128 || c < ' ' ) 2250 c = '?'; 2251 2252 if( italic_shear ) 2253 { 2254 if( ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) 2255 { 2256 if( !(font->ascii[0] & CV_FONT_ITALIC_ALPHA) ) 2257 shear += italic_shear; 2258 } 2259 else if( '0' <= c && c <= '9' ) 2260 { 2261 if( !(font->ascii[0] & CV_FONT_ITALIC_DIGIT) ) 2262 shear += italic_shear; 2263 } 2264 else if( c < 'A' ) 2265 { 2266 if( !(font->ascii[0] & CV_FONT_ITALIC_PUNCT) ) 2267 shear += italic_shear; 2268 } 2269 else 2270 { 2271 shear += italic_shear; 2272 } 2273 } 2274 2275 ptr = faces[font->ascii[(c-' ')+1]]; 2276 p.x = (unsigned char)ptr[0] - 'R'; 2277 p.y = (unsigned char)ptr[1] - 'R'; 2278 dx = p.y*hscale; 2279 view_x -= p.x*hscale; 2280 count = 0; 2281 2282 for( ptr += 2;; ) 2283 { 2284 if( *ptr == ' ' || !*ptr ) 2285 { 2286 if( count > 1 ) 2287 icvPolyLine( mat, pt, count, 0, buf, thickness, line_type, XY_SHIFT ); 2288 if( !*ptr++ ) 2289 break; 2290 count = 0; 2291 } 2292 else 2293 { 2294 p.x = (unsigned char)ptr[0] - 'R'; 2295 p.y = (unsigned char)ptr[1] - 'R'; 2296 ptr += 2; 2297 pt[count].x = p.x*hscale - p.y*shear + view_x; 2298 pt[count++].y = p.y*vscale + view_y; 2299 } 2300 } 2301 view_x += dx; 2302 } 2303 2304 __END__; 2305} 2306 2307CV_IMPL void 2308cvInitFont( CvFont *font, int font_face, double hscale, double vscale, 2309 double shear, int thickness, int line_type ) 2310{ 2311 CV_FUNCNAME( "cvInitFont" ); 2312 2313 __BEGIN__; 2314 2315 int is_italic = font_face & CV_FONT_ITALIC; 2316 2317 if( !font ) 2318 CV_ERROR( CV_StsNullPtr, "" ); 2319 2320 if( hscale <= 0 || vscale <= 0 || thickness < 0 ) 2321 CV_ERROR( CV_StsOutOfRange, "" ); 2322 2323 switch( (font_face & 7) ) 2324 { 2325 case CV_FONT_HERSHEY_SIMPLEX: 2326 font->ascii = icvHersheySimplex; 2327 break; 2328 case CV_FONT_HERSHEY_PLAIN: 2329 font->ascii = !is_italic ? icvHersheyPlain : icvHersheyPlainItalic; 2330 break; 2331 case CV_FONT_HERSHEY_DUPLEX: 2332 font->ascii = icvHersheyDuplex; 2333 break; 2334 case CV_FONT_HERSHEY_COMPLEX: 2335 font->ascii = !is_italic ? icvHersheyComplex : icvHersheyComplexItalic; 2336 break; 2337 case CV_FONT_HERSHEY_TRIPLEX: 2338 font->ascii = !is_italic ? icvHersheyTriplex : icvHersheyTriplexItalic; 2339 break; 2340 case CV_FONT_HERSHEY_COMPLEX_SMALL: 2341 font->ascii = !is_italic ? icvHersheyComplexSmall : icvHersheyComplexSmallItalic; 2342 break; 2343 case CV_FONT_HERSHEY_SCRIPT_SIMPLEX: 2344 font->ascii = icvHersheyScriptSimplex; 2345 break; 2346 case CV_FONT_HERSHEY_SCRIPT_COMPLEX: 2347 font->ascii = icvHersheyScriptComplex; 2348 break; 2349 default: 2350 CV_ERROR( CV_StsOutOfRange, "Unknown font type" ); 2351 } 2352 2353 font->font_face = font_face; 2354 font->hscale = (float)hscale; 2355 font->vscale = (float)vscale; 2356 font->thickness = thickness; 2357 font->shear = (float)shear; 2358 font->greek = font->cyrillic = 0; 2359 font->line_type = line_type; 2360 2361 __END__; 2362} 2363 2364 2365CV_IMPL void 2366cvGetTextSize( const char *text, const CvFont *font, CvSize *size, int *_base_line ) 2367{ 2368 CV_FUNCNAME( "cvGetTextSize" ); 2369 2370 __BEGIN__; 2371 2372 float view_x = 0; 2373 int base_line, cap_line; 2374 2375 int i; 2376 const char **faces = icvHersheyGlyphs; 2377 2378 if( !text || !font || !font->ascii || !size ) 2379 CV_ERROR( CV_StsNullPtr, "" ); 2380 2381 base_line = (font->ascii[0] & 15); 2382 cap_line = (font->ascii[0] >> 4) & 15; 2383 if( _base_line ) 2384 *_base_line = cvRound(base_line*font->vscale); 2385 size->height = cvRound((cap_line + base_line)*font->vscale + font->thickness); 2386 2387 for( i = 0; text[i] != '\0'; i++ ) 2388 { 2389 int c = (uchar)text[i]; 2390 const char* ptr; 2391 CvPoint p; 2392 2393 if( c > 128 || c < ' ' ) 2394 c = '?'; 2395 2396 ptr = faces[font->ascii[(c-' ')+1]]; 2397 p.x = (unsigned char)ptr[0] - 'R'; 2398 p.y = (unsigned char)ptr[1] - 'R'; 2399 view_x += (p.y - p.x)*font->hscale; 2400 } 2401 2402 size->width = cvRound(view_x + font->thickness); 2403 2404 __END__; 2405} 2406 2407 2408static const CvPoint icvCodeDeltas[8] = 2409{ {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1} }; 2410 2411#define CV_ADJUST_EDGE_COUNT( count, seq ) \ 2412 ((count) -= ((count) == (seq)->total && !CV_IS_SEQ_CLOSED(seq))) 2413 2414CV_IMPL void 2415cvDrawContours( void* img, CvSeq* contour, 2416 CvScalar externalColor, CvScalar holeColor, 2417 int maxLevel, int thickness, 2418 int line_type, CvPoint offset ) 2419{ 2420 CvSeq *contour0 = contour, *h_next = 0; 2421 CvMemStorage* st = 0; 2422 CvSeq* tseq = 0; 2423 CvContour* edges = 0; 2424 CvSeqWriter writer; 2425 CvTreeNodeIterator iterator; 2426 2427 CV_FUNCNAME( "cvDrawContours" ); 2428 2429 __BEGIN__; 2430 2431 int coi = 0; 2432 CvMat stub, *mat = (CvMat*)img; 2433 double ext_buf[4], hole_buf[4]; 2434 2435 CV_CALL( mat = cvGetMat( mat, &stub, &coi )); 2436 2437 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U ) 2438 line_type = 8; 2439 2440 if( !contour ) 2441 EXIT; 2442 2443 if( coi != 0 ) 2444 CV_ERROR( CV_BadCOI, cvUnsupportedFormat ); 2445 2446 if( thickness < -1 || thickness > 255 ) 2447 CV_ERROR( CV_StsOutOfRange, "" ); 2448 2449 CV_CALL( cvScalarToRawData( &externalColor, ext_buf, mat->type, 0 )); 2450 CV_CALL( cvScalarToRawData( &holeColor, hole_buf, mat->type, 0 )); 2451 2452 if( maxLevel < 0 ) 2453 { 2454 h_next = contour->h_next; 2455 contour->h_next = 0; 2456 maxLevel = -maxLevel+1; 2457 } 2458 2459 if( thickness < 0 ) 2460 { 2461 if( contour->storage ) 2462 st = cvCreateChildMemStorage( contour->storage ); 2463 else 2464 st = cvCreateMemStorage( CV_DRAWING_STORAGE_BLOCK ); 2465 tseq = cvCreateSeq( 0, sizeof(CvContour), sizeof(CvPoint), st ); 2466 edges = (CvContour*)cvCreateSeq( 0, sizeof(CvContour), sizeof(CvPolyEdge), st ); 2467 } 2468 2469 memset( &writer, 0, sizeof(writer)); 2470 2471 cvInitTreeNodeIterator( &iterator, contour, maxLevel ); 2472 2473 while( (contour = (CvSeq*)cvNextTreeNode( &iterator )) != 0 ) 2474 { 2475 CvSeqReader reader; 2476 int i, count = contour->total; 2477 int elem_type = CV_MAT_TYPE(contour->flags); 2478 void* clr = (contour->flags & CV_SEQ_FLAG_HOLE) == 0 ? ext_buf : hole_buf; 2479 2480 cvStartReadSeq( contour, &reader, 0 ); 2481 2482 if( CV_IS_SEQ_CHAIN_CONTOUR( contour )) 2483 { 2484 CvPoint pt = ((CvChain*)contour)->origin; 2485 CvPoint prev_pt = pt; 2486 char prev_code = reader.ptr ? reader.ptr[0] : '\0'; 2487 2488 if( thickness < 0 ) 2489 { 2490 cvClearSeq( tseq ); 2491 cvStartAppendToSeq( tseq, &writer ); 2492 CV_WRITE_SEQ_ELEM( pt, writer ); 2493 } 2494 2495 prev_pt.x += offset.x; 2496 prev_pt.y += offset.y; 2497 2498 for( i = 0; i < count; i++ ) 2499 { 2500 char code; 2501 CV_READ_SEQ_ELEM( code, reader ); 2502 2503 assert( (code & ~7) == 0 ); 2504 2505 if( code != prev_code ) 2506 { 2507 prev_code = code; 2508 if( thickness >= 0 ) 2509 { 2510 icvThickLine( mat, prev_pt, pt, clr, thickness, line_type, 2, 0 ); 2511 } 2512 else 2513 { 2514 CV_WRITE_SEQ_ELEM( pt, writer ); 2515 } 2516 prev_pt = pt; 2517 } 2518 2519 pt.x += icvCodeDeltas[(int)code].x; 2520 pt.y += icvCodeDeltas[(int)code].y; 2521 } 2522 2523 if( thickness >= 0 ) 2524 { 2525 icvThickLine( mat, prev_pt, ((CvChain*)contour)->origin, 2526 clr, thickness, line_type, 2, 0 ); 2527 } 2528 else 2529 { 2530 CV_WRITE_SEQ_ELEM( pt, writer ); 2531 cvEndWriteSeq( &writer ); 2532 CV_CALL( icvCollectPolyEdges( mat, tseq, edges, ext_buf, line_type, 0 )); 2533 } 2534 } 2535 else if( CV_IS_SEQ_POLYLINE( contour )) 2536 { 2537 if( thickness >= 0 ) 2538 { 2539 CvPoint pt1, pt2; 2540 int shift = 0; 2541 2542 count -= !CV_IS_SEQ_CLOSED(contour); 2543 if( elem_type == CV_32SC2 ) 2544 { 2545 CV_READ_SEQ_ELEM( pt1, reader ); 2546 pt1.x += offset.x; 2547 pt1.y += offset.y; 2548 } 2549 else 2550 { 2551 CvPoint2D32f pt1f; 2552 CV_READ_SEQ_ELEM( pt1f, reader ); 2553 pt1.x = cvRound( (pt1f.x + offset.x) * XY_ONE ); 2554 pt1.y = cvRound( (pt1f.y + offset.y) * XY_ONE ); 2555 shift = XY_SHIFT; 2556 } 2557 2558 for( i = 0; i < count; i++ ) 2559 { 2560 if( elem_type == CV_32SC2 ) 2561 { 2562 CV_READ_SEQ_ELEM( pt2, reader ); 2563 pt2.x += offset.x; 2564 pt2.y += offset.y; 2565 } 2566 else 2567 { 2568 CvPoint2D32f pt2f; 2569 CV_READ_SEQ_ELEM( pt2f, reader ); 2570 pt2.x = cvRound( pt2f.x * XY_ONE ); 2571 pt2.y = cvRound( pt2f.y * XY_ONE ); 2572 } 2573 icvThickLine( mat, pt1, pt2, clr, thickness, line_type, 2, shift ); 2574 pt1 = pt2; 2575 } 2576 } 2577 else 2578 { 2579 CV_CALL( icvCollectPolyEdges( mat, contour, edges, ext_buf, line_type, 0, offset )); 2580 } 2581 } 2582 } 2583 2584 if( thickness < 0 ) 2585 { 2586 CV_CALL( icvFillEdgeCollection( mat, edges, ext_buf )); 2587 } 2588 2589 __END__; 2590 2591 if( h_next && contour0 ) 2592 contour0->h_next = h_next; 2593 2594 cvReleaseMemStorage( &st ); 2595} 2596 2597/* End of file. */ 2598