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 "precomp.hpp"
42
43 namespace cv
44 {
45
46 enum { XY_SHIFT = 16, XY_ONE = 1 << XY_SHIFT, DRAWING_STORAGE_BLOCK = (1<<12) - 256 };
47
48 static const int MAX_THICKNESS = 32767;
49
50 struct PolyEdge
51 {
PolyEdgecv::PolyEdge52 PolyEdge() : y0(0), y1(0), x(0), dx(0), next(0) {}
53 //PolyEdge(int _y0, int _y1, int _x, int _dx) : y0(_y0), y1(_y1), x(_x), dx(_dx) {}
54
55 int y0, y1;
56 int64 x, dx;
57 PolyEdge *next;
58 };
59
60 static void
61 CollectPolyEdges( Mat& img, const Point2l* v, int npts,
62 std::vector<PolyEdge>& edges, const void* color, int line_type,
63 int shift, Point offset=Point() );
64
65 static void
66 FillEdgeCollection( Mat& img, std::vector<PolyEdge>& edges, const void* color );
67
68 static void
69 PolyLine( Mat& img, const Point2l* v, int npts, bool closed,
70 const void* color, int thickness, int line_type, int shift );
71
72 static void
73 FillConvexPoly( Mat& img, const Point2l* v, int npts,
74 const void* color, int line_type, int shift );
75
76 /****************************************************************************************\
77 * Lines *
78 \****************************************************************************************/
79
clipLine(Size img_size,Point & pt1,Point & pt2)80 bool clipLine( Size img_size, Point& pt1, Point& pt2 )
81 {
82 Point2l p1(pt1);
83 Point2l p2(pt2);
84 bool inside = clipLine(Size2l(img_size.width, img_size.height), p1, p2);
85 pt1.x = (int)p1.x;
86 pt1.y = (int)p1.y;
87 pt2.x = (int)p2.x;
88 pt2.y = (int)p2.y;
89 return inside;
90 }
91
clipLine(Size2l img_size,Point2l & pt1,Point2l & pt2)92 bool clipLine( Size2l img_size, Point2l& pt1, Point2l& pt2 )
93 {
94 CV_INSTRUMENT_REGION();
95
96 int c1, c2;
97 int64 right = img_size.width-1, bottom = img_size.height-1;
98
99 if( img_size.width <= 0 || img_size.height <= 0 )
100 return false;
101
102 int64 &x1 = pt1.x, &y1 = pt1.y, &x2 = pt2.x, &y2 = pt2.y;
103 c1 = (x1 < 0) + (x1 > right) * 2 + (y1 < 0) * 4 + (y1 > bottom) * 8;
104 c2 = (x2 < 0) + (x2 > right) * 2 + (y2 < 0) * 4 + (y2 > bottom) * 8;
105
106 if( (c1 & c2) == 0 && (c1 | c2) != 0 )
107 {
108 int64 a;
109 if( c1 & 12 )
110 {
111 a = c1 < 8 ? 0 : bottom;
112 x1 += (int64)((double)(a - y1) * (x2 - x1) / (y2 - y1));
113 y1 = a;
114 c1 = (x1 < 0) + (x1 > right) * 2;
115 }
116 if( c2 & 12 )
117 {
118 a = c2 < 8 ? 0 : bottom;
119 x2 += (int64)((double)(a - y2) * (x2 - x1) / (y2 - y1));
120 y2 = a;
121 c2 = (x2 < 0) + (x2 > right) * 2;
122 }
123 if( (c1 & c2) == 0 && (c1 | c2) != 0 )
124 {
125 if( c1 )
126 {
127 a = c1 == 1 ? 0 : right;
128 y1 += (int64)((double)(a - x1) * (y2 - y1) / (x2 - x1));
129 x1 = a;
130 c1 = 0;
131 }
132 if( c2 )
133 {
134 a = c2 == 1 ? 0 : right;
135 y2 += (int64)((double)(a - x2) * (y2 - y1) / (x2 - x1));
136 x2 = a;
137 c2 = 0;
138 }
139 }
140
141 assert( (c1 & c2) != 0 || (x1 | y1 | x2 | y2) >= 0 );
142 }
143
144 return (c1 | c2) == 0;
145 }
146
clipLine(Rect img_rect,Point & pt1,Point & pt2)147 bool clipLine( Rect img_rect, Point& pt1, Point& pt2 )
148 {
149 CV_INSTRUMENT_REGION();
150
151 Point tl = img_rect.tl();
152 pt1 -= tl; pt2 -= tl;
153 bool inside = clipLine(img_rect.size(), pt1, pt2);
154 pt1 += tl; pt2 += tl;
155
156 return inside;
157 }
158
init(const Mat * img,Rect rect,Point pt1_,Point pt2_,int connectivity,bool leftToRight)159 void LineIterator::init( const Mat* img, Rect rect, Point pt1_, Point pt2_, int connectivity, bool leftToRight )
160 {
161 CV_Assert( connectivity == 8 || connectivity == 4 );
162
163 count = -1;
164 p = Point(0, 0);
165 ptr0 = ptr = 0;
166 step = elemSize = 0;
167 ptmode = !img;
168
169 Point pt1 = pt1_ - rect.tl();
170 Point pt2 = pt2_ - rect.tl();
171
172 if( (unsigned)pt1.x >= (unsigned)(rect.width) ||
173 (unsigned)pt2.x >= (unsigned)(rect.width) ||
174 (unsigned)pt1.y >= (unsigned)(rect.height) ||
175 (unsigned)pt2.y >= (unsigned)(rect.height) )
176 {
177 if( !clipLine(Size(rect.width, rect.height), pt1, pt2) )
178 {
179 err = plusDelta = minusDelta = plusStep = minusStep = plusShift = minusShift = count = 0;
180 return;
181 }
182 }
183
184 pt1 += rect.tl();
185 pt2 += rect.tl();
186
187 int delta_x = 1, delta_y = 1;
188 int dx = pt2.x - pt1.x;
189 int dy = pt2.y - pt1.y;
190
191 if( dx < 0 )
192 {
193 if( leftToRight )
194 {
195 dx = -dx;
196 dy = -dy;
197 pt1 = pt2;
198 }
199 else
200 {
201 dx = -dx;
202 delta_x = -1;
203 }
204 }
205
206 if( dy < 0 )
207 {
208 dy = -dy;
209 delta_y = -1;
210 }
211
212 bool vert = dy > dx;
213 if( vert )
214 {
215 std::swap(dx, dy);
216 std::swap(delta_x, delta_y);
217 }
218
219 CV_Assert( dx >= 0 && dy >= 0 );
220
221 if( connectivity == 8 )
222 {
223 err = dx - (dy + dy);
224 plusDelta = dx + dx;
225 minusDelta = -(dy + dy);
226 minusShift = delta_x;
227 plusShift = 0;
228 minusStep = 0;
229 plusStep = delta_y;
230 count = dx + 1;
231 }
232 else /* connectivity == 4 */
233 {
234 err = 0;
235 plusDelta = (dx + dx) + (dy + dy);
236 minusDelta = -(dy + dy);
237 minusShift = delta_x;
238 plusShift = -delta_x;
239 minusStep = 0;
240 plusStep = delta_y;
241 count = dx + dy + 1;
242 }
243
244 if( vert )
245 {
246 std::swap(plusStep, plusShift);
247 std::swap(minusStep, minusShift);
248 }
249
250 p = pt1;
251 if( !ptmode )
252 {
253 ptr0 = img->ptr();
254 step = (int)img->step;
255 elemSize = (int)img->elemSize();
256 ptr = (uchar*)ptr0 + (size_t)p.y*step + (size_t)p.x*elemSize;
257 plusStep = plusStep*step + plusShift*elemSize;
258 minusStep = minusStep*step + minusShift*elemSize;
259 }
260 }
261
262 static void
Line(Mat & img,Point pt1,Point pt2,const void * _color,int connectivity=8)263 Line( Mat& img, Point pt1, Point pt2,
264 const void* _color, int connectivity = 8 )
265 {
266 if( connectivity == 0 )
267 connectivity = 8;
268 else if( connectivity == 1 )
269 connectivity = 4;
270
271 LineIterator iterator(img, pt1, pt2, connectivity, true);
272 int i, count = iterator.count;
273 int pix_size = (int)img.elemSize();
274 const uchar* color = (const uchar*)_color;
275
276 if( pix_size == 3 )
277 {
278 for( i = 0; i < count; i++, ++iterator )
279 {
280 uchar* ptr = *iterator;
281 ptr[0] = color[0];
282 ptr[1] = color[1];
283 ptr[2] = color[2];
284 }
285 }
286 else
287 {
288 for( i = 0; i < count; i++, ++iterator )
289 {
290 uchar* ptr = *iterator;
291 if( pix_size == 1 )
292 ptr[0] = color[0];
293 else
294 memcpy( *iterator, color, pix_size );
295 }
296 }
297 }
298
299
300 /* Correction table depent on the slope */
301 static const uchar SlopeCorrTable[] = {
302 181, 181, 181, 182, 182, 183, 184, 185, 187, 188, 190, 192, 194, 196, 198, 201,
303 203, 206, 209, 211, 214, 218, 221, 224, 227, 231, 235, 238, 242, 246, 250, 254
304 };
305
306 /* Gaussian for antialiasing filter */
307 static const int FilterTable[] = {
308 168, 177, 185, 194, 202, 210, 218, 224, 231, 236, 241, 246, 249, 252, 254, 254,
309 254, 254, 252, 249, 246, 241, 236, 231, 224, 218, 210, 202, 194, 185, 177, 168,
310 158, 149, 140, 131, 122, 114, 105, 97, 89, 82, 75, 68, 62, 56, 50, 45,
311 40, 36, 32, 28, 25, 22, 19, 16, 14, 12, 11, 9, 8, 7, 5, 5
312 };
313
314 static void
LineAA(Mat & img,Point2l pt1,Point2l pt2,const void * color)315 LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color )
316 {
317 int64 dx, dy;
318 int ecount, scount = 0;
319 int slope;
320 int64 ax, ay;
321 int64 x_step, y_step;
322 int64 i, j;
323 int ep_table[9];
324 int cb = ((uchar*)color)[0], cg = ((uchar*)color)[1], cr = ((uchar*)color)[2], ca = ((uchar*)color)[3];
325 int _cb, _cg, _cr, _ca;
326 int nch = img.channels();
327 uchar* ptr = img.ptr();
328 size_t step = img.step;
329 Size2l size0(img.size()), size = size0;
330
331 if( !((nch == 1 || nch == 3 || nch == 4) && img.depth() == CV_8U) )
332 {
333 Line(img, Point((int)(pt1.x>>XY_SHIFT), (int)(pt1.y>>XY_SHIFT)), Point((int)(pt2.x>>XY_SHIFT), (int)(pt2.y>>XY_SHIFT)), color);
334 return;
335 }
336
337 size.width <<= XY_SHIFT;
338 size.height <<= XY_SHIFT;
339 if( !clipLine( size, pt1, pt2 ))
340 return;
341
342 dx = pt2.x - pt1.x;
343 dy = pt2.y - pt1.y;
344
345 j = dx < 0 ? -1 : 0;
346 ax = (dx ^ j) - j;
347 i = dy < 0 ? -1 : 0;
348 ay = (dy ^ i) - i;
349
350 if( ax > ay )
351 {
352 dy = (dy ^ j) - j;
353 pt1.x ^= pt2.x & j;
354 pt2.x ^= pt1.x & j;
355 pt1.x ^= pt2.x & j;
356 pt1.y ^= pt2.y & j;
357 pt2.y ^= pt1.y & j;
358 pt1.y ^= pt2.y & j;
359
360 x_step = XY_ONE;
361 y_step = (dy << XY_SHIFT) / (ax | 1);
362 pt2.x += XY_ONE;
363 ecount = (int)((pt2.x >> XY_SHIFT) - (pt1.x >> XY_SHIFT));
364 j = -(pt1.x & (XY_ONE - 1));
365 pt1.y += ((y_step * j) >> XY_SHIFT) + (XY_ONE >> 1);
366 slope = (y_step >> (XY_SHIFT - 5)) & 0x3f;
367 slope ^= (y_step < 0 ? 0x3f : 0);
368
369 /* Get 4-bit fractions for end-point adjustments */
370 i = (pt1.x >> (XY_SHIFT - 7)) & 0x78;
371 j = (pt2.x >> (XY_SHIFT - 7)) & 0x78;
372 }
373 else
374 {
375 dx = (dx ^ i) - i;
376 pt1.x ^= pt2.x & i;
377 pt2.x ^= pt1.x & i;
378 pt1.x ^= pt2.x & i;
379 pt1.y ^= pt2.y & i;
380 pt2.y ^= pt1.y & i;
381 pt1.y ^= pt2.y & i;
382
383 x_step = (dx << XY_SHIFT) / (ay | 1);
384 y_step = XY_ONE;
385 pt2.y += XY_ONE;
386 ecount = (int)((pt2.y >> XY_SHIFT) - (pt1.y >> XY_SHIFT));
387 j = -(pt1.y & (XY_ONE - 1));
388 pt1.x += ((x_step * j) >> XY_SHIFT) + (XY_ONE >> 1);
389 slope = (x_step >> (XY_SHIFT - 5)) & 0x3f;
390 slope ^= (x_step < 0 ? 0x3f : 0);
391
392 /* Get 4-bit fractions for end-point adjustments */
393 i = (pt1.y >> (XY_SHIFT - 7)) & 0x78;
394 j = (pt2.y >> (XY_SHIFT - 7)) & 0x78;
395 }
396
397 slope = (slope & 0x20) ? 0x100 : SlopeCorrTable[slope];
398
399 /* Calc end point correction table */
400 {
401 int t0 = slope << 7;
402 int t1 = ((0x78 - (int)i) | 4) * slope;
403 int t2 = ((int)j | 4) * slope;
404
405 ep_table[0] = 0;
406 ep_table[8] = slope;
407 ep_table[1] = ep_table[3] = ((((j - i) & 0x78) | 4) * slope >> 8) & 0x1ff;
408 ep_table[2] = (t1 >> 8) & 0x1ff;
409 ep_table[4] = ((((j - i) + 0x80) | 4) * slope >> 8) & 0x1ff;
410 ep_table[5] = ((t1 + t0) >> 8) & 0x1ff;
411 ep_table[6] = (t2 >> 8) & 0x1ff;
412 ep_table[7] = ((t2 + t0) >> 8) & 0x1ff;
413 }
414
415 if( nch == 3 )
416 {
417 #define ICV_PUT_POINT(x, y) \
418 { \
419 uchar* tptr = ptr + (x)*3 + (y)*step; \
420 _cb = tptr[0]; \
421 _cb += ((cb - _cb)*a + 127)>> 8;\
422 _cb += ((cb - _cb)*a + 127)>> 8;\
423 _cg = tptr[1]; \
424 _cg += ((cg - _cg)*a + 127)>> 8;\
425 _cg += ((cg - _cg)*a + 127)>> 8;\
426 _cr = tptr[2]; \
427 _cr += ((cr - _cr)*a + 127)>> 8;\
428 _cr += ((cr - _cr)*a + 127)>> 8;\
429 tptr[0] = (uchar)_cb; \
430 tptr[1] = (uchar)_cg; \
431 tptr[2] = (uchar)_cr; \
432 }
433 if( ax > ay )
434 {
435 int x = (int)(pt1.x >> XY_SHIFT);
436
437 for( ; ecount >= 0; x++, pt1.y += y_step, scount++, ecount-- )
438 {
439 if( (unsigned)x >= (unsigned)size0.width )
440 continue;
441 int y = (int)((pt1.y >> XY_SHIFT) - 1);
442
443 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
444 (((ecount >= 2) + 1) & (ecount | 2))];
445 int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
446
447 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
448 if( (unsigned)y < (unsigned)size0.height )
449 ICV_PUT_POINT(x, y)
450
451 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
452 if( (unsigned)(y+1) < (unsigned)size0.height )
453 ICV_PUT_POINT(x, y+1)
454
455 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
456 if( (unsigned)(y+2) < (unsigned)size0.height )
457 ICV_PUT_POINT(x, y+2)
458 }
459 }
460 else
461 {
462 int y = (int)(pt1.y >> XY_SHIFT);
463
464 for( ; ecount >= 0; y++, pt1.x += x_step, scount++, ecount-- )
465 {
466 if( (unsigned)y >= (unsigned)size0.height )
467 continue;
468 int x = (int)((pt1.x >> XY_SHIFT) - 1);
469 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
470 (((ecount >= 2) + 1) & (ecount | 2))];
471 int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
472
473 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
474 if( (unsigned)x < (unsigned)size0.width )
475 ICV_PUT_POINT(x, y)
476
477 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
478 if( (unsigned)(x+1) < (unsigned)size0.width )
479 ICV_PUT_POINT(x+1, y)
480
481 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
482 if( (unsigned)(x+2) < (unsigned)size0.width )
483 ICV_PUT_POINT(x+2, y)
484 }
485 }
486 #undef ICV_PUT_POINT
487 }
488 else if(nch == 1)
489 {
490 #define ICV_PUT_POINT(x, y) \
491 { \
492 uchar* tptr = ptr + (x) + (y) * step; \
493 _cb = tptr[0]; \
494 _cb += ((cb - _cb)*a + 127)>> 8;\
495 _cb += ((cb - _cb)*a + 127)>> 8;\
496 tptr[0] = (uchar)_cb; \
497 }
498
499 if( ax > ay )
500 {
501 int x = (int)(pt1.x >> XY_SHIFT);
502
503 for( ; ecount >= 0; x++, pt1.y += y_step, scount++, ecount-- )
504 {
505 if( (unsigned)x >= (unsigned)size0.width )
506 continue;
507 int y = (int)((pt1.y >> XY_SHIFT) - 1);
508
509 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
510 (((ecount >= 2) + 1) & (ecount | 2))];
511 int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
512
513 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
514 if( (unsigned)y < (unsigned)size0.height )
515 ICV_PUT_POINT(x, y)
516
517 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
518 if( (unsigned)(y+1) < (unsigned)size0.height )
519 ICV_PUT_POINT(x, y+1)
520
521 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
522 if( (unsigned)(y+2) < (unsigned)size0.height )
523 ICV_PUT_POINT(x, y+2)
524 }
525 }
526 else
527 {
528 int y = (int)(pt1.y >> XY_SHIFT);
529
530 for( ; ecount >= 0; y++, pt1.x += x_step, scount++, ecount-- )
531 {
532 if( (unsigned)y >= (unsigned)size0.height )
533 continue;
534 int x = (int)((pt1.x >> XY_SHIFT) - 1);
535 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
536 (((ecount >= 2) + 1) & (ecount | 2))];
537 int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
538
539 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
540 if( (unsigned)x < (unsigned)size0.width )
541 ICV_PUT_POINT(x, y)
542
543 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
544 if( (unsigned)(x+1) < (unsigned)size0.width )
545 ICV_PUT_POINT(x+1, y)
546
547 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
548 if( (unsigned)(x+2) < (unsigned)size0.width )
549 ICV_PUT_POINT(x+2, y)
550 }
551 }
552 #undef ICV_PUT_POINT
553 }
554 else
555 {
556 #define ICV_PUT_POINT(x, y) \
557 { \
558 uchar* tptr = ptr + (x)*4 + (y)*step; \
559 _cb = tptr[0]; \
560 _cb += ((cb - _cb)*a + 127)>> 8;\
561 _cb += ((cb - _cb)*a + 127)>> 8;\
562 _cg = tptr[1]; \
563 _cg += ((cg - _cg)*a + 127)>> 8;\
564 _cg += ((cg - _cg)*a + 127)>> 8;\
565 _cr = tptr[2]; \
566 _cr += ((cr - _cr)*a + 127)>> 8;\
567 _cr += ((cr - _cr)*a + 127)>> 8;\
568 _ca = tptr[3]; \
569 _ca += ((ca - _ca)*a + 127)>> 8;\
570 _ca += ((ca - _ca)*a + 127)>> 8;\
571 tptr[0] = (uchar)_cb; \
572 tptr[1] = (uchar)_cg; \
573 tptr[2] = (uchar)_cr; \
574 tptr[3] = (uchar)_ca; \
575 }
576 if( ax > ay )
577 {
578 int x = (int)(pt1.x >> XY_SHIFT);
579
580 for( ; ecount >= 0; x++, pt1.y += y_step, scount++, ecount-- )
581 {
582 if( (unsigned)x >= (unsigned)size0.width )
583 continue;
584 int y = (int)((pt1.y >> XY_SHIFT) - 1);
585
586 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
587 (((ecount >= 2) + 1) & (ecount | 2))];
588 int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
589
590 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
591 if( (unsigned)y < (unsigned)size0.height )
592 ICV_PUT_POINT(x, y)
593
594 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
595 if( (unsigned)(y+1) < (unsigned)size0.height )
596 ICV_PUT_POINT(x, y+1)
597
598 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
599 if( (unsigned)(y+2) < (unsigned)size0.height )
600 ICV_PUT_POINT(x, y+2)
601 }
602 }
603 else
604 {
605 int y = (int)(pt1.y >> XY_SHIFT);
606
607 for( ; ecount >= 0; y++, pt1.x += x_step, scount++, ecount-- )
608 {
609 if( (unsigned)y >= (unsigned)size0.height )
610 continue;
611 int x = (int)((pt1.x >> XY_SHIFT) - 1);
612 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
613 (((ecount >= 2) + 1) & (ecount | 2))];
614 int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
615
616 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
617 if( (unsigned)x < (unsigned)size0.width )
618 ICV_PUT_POINT(x, y)
619
620 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
621 if( (unsigned)(x+1) < (unsigned)size0.width )
622 ICV_PUT_POINT(x+1, y)
623
624 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
625 if( (unsigned)(x+2) < (unsigned)size0.width )
626 ICV_PUT_POINT(x+2, y)
627 }
628 }
629 #undef ICV_PUT_POINT
630 }
631 }
632
633
634 static void
Line2(Mat & img,Point2l pt1,Point2l pt2,const void * color)635 Line2( Mat& img, Point2l pt1, Point2l pt2, const void* color)
636 {
637 int64 dx, dy;
638 int ecount;
639 int64 ax, ay;
640 int64 i, j;
641 int x, y;
642 int64 x_step, y_step;
643 int cb = ((uchar*)color)[0];
644 int cg = ((uchar*)color)[1];
645 int cr = ((uchar*)color)[2];
646 int pix_size = (int)img.elemSize();
647 uchar *ptr = img.ptr(), *tptr;
648 size_t step = img.step;
649 Size size = img.size();
650
651 //assert( img && (nch == 1 || nch == 3) && img.depth() == CV_8U );
652
653 Size2l sizeScaled(((int64)size.width) << XY_SHIFT, ((int64)size.height) << XY_SHIFT);
654 if( !clipLine( sizeScaled, pt1, pt2 ))
655 return;
656
657 dx = pt2.x - pt1.x;
658 dy = pt2.y - pt1.y;
659
660 j = dx < 0 ? -1 : 0;
661 ax = (dx ^ j) - j;
662 i = dy < 0 ? -1 : 0;
663 ay = (dy ^ i) - i;
664
665 if( ax > ay )
666 {
667 dy = (dy ^ j) - j;
668 pt1.x ^= pt2.x & j;
669 pt2.x ^= pt1.x & j;
670 pt1.x ^= pt2.x & j;
671 pt1.y ^= pt2.y & j;
672 pt2.y ^= pt1.y & j;
673 pt1.y ^= pt2.y & j;
674
675 x_step = XY_ONE;
676 y_step = (dy << XY_SHIFT) / (ax | 1);
677 ecount = (int)((pt2.x - pt1.x) >> XY_SHIFT);
678 }
679 else
680 {
681 dx = (dx ^ i) - i;
682 pt1.x ^= pt2.x & i;
683 pt2.x ^= pt1.x & i;
684 pt1.x ^= pt2.x & i;
685 pt1.y ^= pt2.y & i;
686 pt2.y ^= pt1.y & i;
687 pt1.y ^= pt2.y & i;
688
689 x_step = (dx << XY_SHIFT) / (ay | 1);
690 y_step = XY_ONE;
691 ecount = (int)((pt2.y - pt1.y) >> XY_SHIFT);
692 }
693
694 pt1.x += (XY_ONE >> 1);
695 pt1.y += (XY_ONE >> 1);
696
697 if( pix_size == 3 )
698 {
699 #define ICV_PUT_POINT(_x,_y) \
700 x = (_x); y = (_y); \
701 if( 0 <= x && x < size.width && \
702 0 <= y && y < size.height ) \
703 { \
704 tptr = ptr + y*step + x*3; \
705 tptr[0] = (uchar)cb; \
706 tptr[1] = (uchar)cg; \
707 tptr[2] = (uchar)cr; \
708 }
709
710 ICV_PUT_POINT((int)((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT),
711 (int)((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT));
712
713 if( ax > ay )
714 {
715 pt1.x >>= XY_SHIFT;
716
717 while( ecount >= 0 )
718 {
719 ICV_PUT_POINT((int)(pt1.x), (int)(pt1.y >> XY_SHIFT));
720 pt1.x++;
721 pt1.y += y_step;
722 ecount--;
723 }
724 }
725 else
726 {
727 pt1.y >>= XY_SHIFT;
728
729 while( ecount >= 0 )
730 {
731 ICV_PUT_POINT((int)(pt1.x >> XY_SHIFT), (int)(pt1.y));
732 pt1.x += x_step;
733 pt1.y++;
734 ecount--;
735 }
736 }
737
738 #undef ICV_PUT_POINT
739 }
740 else if( pix_size == 1 )
741 {
742 #define ICV_PUT_POINT(_x,_y) \
743 x = (_x); y = (_y); \
744 if( 0 <= x && x < size.width && \
745 0 <= y && y < size.height ) \
746 { \
747 tptr = ptr + y*step + x;\
748 tptr[0] = (uchar)cb; \
749 }
750
751 ICV_PUT_POINT((int)((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT),
752 (int)((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT));
753
754 if( ax > ay )
755 {
756 pt1.x >>= XY_SHIFT;
757
758 while( ecount >= 0 )
759 {
760 ICV_PUT_POINT((int)(pt1.x), (int)(pt1.y >> XY_SHIFT));
761 pt1.x++;
762 pt1.y += y_step;
763 ecount--;
764 }
765 }
766 else
767 {
768 pt1.y >>= XY_SHIFT;
769
770 while( ecount >= 0 )
771 {
772 ICV_PUT_POINT((int)(pt1.x >> XY_SHIFT), (int)(pt1.y));
773 pt1.x += x_step;
774 pt1.y++;
775 ecount--;
776 }
777 }
778
779 #undef ICV_PUT_POINT
780 }
781 else
782 {
783 #define ICV_PUT_POINT(_x,_y) \
784 x = (_x); y = (_y); \
785 if( 0 <= x && x < size.width && \
786 0 <= y && y < size.height ) \
787 { \
788 tptr = ptr + y*step + x*pix_size;\
789 for( j = 0; j < pix_size; j++ ) \
790 tptr[j] = ((uchar*)color)[j]; \
791 }
792
793 ICV_PUT_POINT((int)((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT),
794 (int)((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT));
795
796 if( ax > ay )
797 {
798 pt1.x >>= XY_SHIFT;
799
800 while( ecount >= 0 )
801 {
802 ICV_PUT_POINT((int)(pt1.x), (int)(pt1.y >> XY_SHIFT));
803 pt1.x++;
804 pt1.y += y_step;
805 ecount--;
806 }
807 }
808 else
809 {
810 pt1.y >>= XY_SHIFT;
811
812 while( ecount >= 0 )
813 {
814 ICV_PUT_POINT((int)(pt1.x >> XY_SHIFT), (int)(pt1.y));
815 pt1.x += x_step;
816 pt1.y++;
817 ecount--;
818 }
819 }
820
821 #undef ICV_PUT_POINT
822 }
823 }
824
825
826 /****************************************************************************************\
827 * Antialiazed Elliptic Arcs via Antialiazed Lines *
828 \****************************************************************************************/
829
830 static const float SinTable[] =
831 { 0.0000000f, 0.0174524f, 0.0348995f, 0.0523360f, 0.0697565f, 0.0871557f,
832 0.1045285f, 0.1218693f, 0.1391731f, 0.1564345f, 0.1736482f, 0.1908090f,
833 0.2079117f, 0.2249511f, 0.2419219f, 0.2588190f, 0.2756374f, 0.2923717f,
834 0.3090170f, 0.3255682f, 0.3420201f, 0.3583679f, 0.3746066f, 0.3907311f,
835 0.4067366f, 0.4226183f, 0.4383711f, 0.4539905f, 0.4694716f, 0.4848096f,
836 0.5000000f, 0.5150381f, 0.5299193f, 0.5446390f, 0.5591929f, 0.5735764f,
837 0.5877853f, 0.6018150f, 0.6156615f, 0.6293204f, 0.6427876f, 0.6560590f,
838 0.6691306f, 0.6819984f, 0.6946584f, 0.7071068f, 0.7193398f, 0.7313537f,
839 0.7431448f, 0.7547096f, 0.7660444f, 0.7771460f, 0.7880108f, 0.7986355f,
840 0.8090170f, 0.8191520f, 0.8290376f, 0.8386706f, 0.8480481f, 0.8571673f,
841 0.8660254f, 0.8746197f, 0.8829476f, 0.8910065f, 0.8987940f, 0.9063078f,
842 0.9135455f, 0.9205049f, 0.9271839f, 0.9335804f, 0.9396926f, 0.9455186f,
843 0.9510565f, 0.9563048f, 0.9612617f, 0.9659258f, 0.9702957f, 0.9743701f,
844 0.9781476f, 0.9816272f, 0.9848078f, 0.9876883f, 0.9902681f, 0.9925462f,
845 0.9945219f, 0.9961947f, 0.9975641f, 0.9986295f, 0.9993908f, 0.9998477f,
846 1.0000000f, 0.9998477f, 0.9993908f, 0.9986295f, 0.9975641f, 0.9961947f,
847 0.9945219f, 0.9925462f, 0.9902681f, 0.9876883f, 0.9848078f, 0.9816272f,
848 0.9781476f, 0.9743701f, 0.9702957f, 0.9659258f, 0.9612617f, 0.9563048f,
849 0.9510565f, 0.9455186f, 0.9396926f, 0.9335804f, 0.9271839f, 0.9205049f,
850 0.9135455f, 0.9063078f, 0.8987940f, 0.8910065f, 0.8829476f, 0.8746197f,
851 0.8660254f, 0.8571673f, 0.8480481f, 0.8386706f, 0.8290376f, 0.8191520f,
852 0.8090170f, 0.7986355f, 0.7880108f, 0.7771460f, 0.7660444f, 0.7547096f,
853 0.7431448f, 0.7313537f, 0.7193398f, 0.7071068f, 0.6946584f, 0.6819984f,
854 0.6691306f, 0.6560590f, 0.6427876f, 0.6293204f, 0.6156615f, 0.6018150f,
855 0.5877853f, 0.5735764f, 0.5591929f, 0.5446390f, 0.5299193f, 0.5150381f,
856 0.5000000f, 0.4848096f, 0.4694716f, 0.4539905f, 0.4383711f, 0.4226183f,
857 0.4067366f, 0.3907311f, 0.3746066f, 0.3583679f, 0.3420201f, 0.3255682f,
858 0.3090170f, 0.2923717f, 0.2756374f, 0.2588190f, 0.2419219f, 0.2249511f,
859 0.2079117f, 0.1908090f, 0.1736482f, 0.1564345f, 0.1391731f, 0.1218693f,
860 0.1045285f, 0.0871557f, 0.0697565f, 0.0523360f, 0.0348995f, 0.0174524f,
861 0.0000000f, -0.0174524f, -0.0348995f, -0.0523360f, -0.0697565f, -0.0871557f,
862 -0.1045285f, -0.1218693f, -0.1391731f, -0.1564345f, -0.1736482f, -0.1908090f,
863 -0.2079117f, -0.2249511f, -0.2419219f, -0.2588190f, -0.2756374f, -0.2923717f,
864 -0.3090170f, -0.3255682f, -0.3420201f, -0.3583679f, -0.3746066f, -0.3907311f,
865 -0.4067366f, -0.4226183f, -0.4383711f, -0.4539905f, -0.4694716f, -0.4848096f,
866 -0.5000000f, -0.5150381f, -0.5299193f, -0.5446390f, -0.5591929f, -0.5735764f,
867 -0.5877853f, -0.6018150f, -0.6156615f, -0.6293204f, -0.6427876f, -0.6560590f,
868 -0.6691306f, -0.6819984f, -0.6946584f, -0.7071068f, -0.7193398f, -0.7313537f,
869 -0.7431448f, -0.7547096f, -0.7660444f, -0.7771460f, -0.7880108f, -0.7986355f,
870 -0.8090170f, -0.8191520f, -0.8290376f, -0.8386706f, -0.8480481f, -0.8571673f,
871 -0.8660254f, -0.8746197f, -0.8829476f, -0.8910065f, -0.8987940f, -0.9063078f,
872 -0.9135455f, -0.9205049f, -0.9271839f, -0.9335804f, -0.9396926f, -0.9455186f,
873 -0.9510565f, -0.9563048f, -0.9612617f, -0.9659258f, -0.9702957f, -0.9743701f,
874 -0.9781476f, -0.9816272f, -0.9848078f, -0.9876883f, -0.9902681f, -0.9925462f,
875 -0.9945219f, -0.9961947f, -0.9975641f, -0.9986295f, -0.9993908f, -0.9998477f,
876 -1.0000000f, -0.9998477f, -0.9993908f, -0.9986295f, -0.9975641f, -0.9961947f,
877 -0.9945219f, -0.9925462f, -0.9902681f, -0.9876883f, -0.9848078f, -0.9816272f,
878 -0.9781476f, -0.9743701f, -0.9702957f, -0.9659258f, -0.9612617f, -0.9563048f,
879 -0.9510565f, -0.9455186f, -0.9396926f, -0.9335804f, -0.9271839f, -0.9205049f,
880 -0.9135455f, -0.9063078f, -0.8987940f, -0.8910065f, -0.8829476f, -0.8746197f,
881 -0.8660254f, -0.8571673f, -0.8480481f, -0.8386706f, -0.8290376f, -0.8191520f,
882 -0.8090170f, -0.7986355f, -0.7880108f, -0.7771460f, -0.7660444f, -0.7547096f,
883 -0.7431448f, -0.7313537f, -0.7193398f, -0.7071068f, -0.6946584f, -0.6819984f,
884 -0.6691306f, -0.6560590f, -0.6427876f, -0.6293204f, -0.6156615f, -0.6018150f,
885 -0.5877853f, -0.5735764f, -0.5591929f, -0.5446390f, -0.5299193f, -0.5150381f,
886 -0.5000000f, -0.4848096f, -0.4694716f, -0.4539905f, -0.4383711f, -0.4226183f,
887 -0.4067366f, -0.3907311f, -0.3746066f, -0.3583679f, -0.3420201f, -0.3255682f,
888 -0.3090170f, -0.2923717f, -0.2756374f, -0.2588190f, -0.2419219f, -0.2249511f,
889 -0.2079117f, -0.1908090f, -0.1736482f, -0.1564345f, -0.1391731f, -0.1218693f,
890 -0.1045285f, -0.0871557f, -0.0697565f, -0.0523360f, -0.0348995f, -0.0174524f,
891 -0.0000000f, 0.0174524f, 0.0348995f, 0.0523360f, 0.0697565f, 0.0871557f,
892 0.1045285f, 0.1218693f, 0.1391731f, 0.1564345f, 0.1736482f, 0.1908090f,
893 0.2079117f, 0.2249511f, 0.2419219f, 0.2588190f, 0.2756374f, 0.2923717f,
894 0.3090170f, 0.3255682f, 0.3420201f, 0.3583679f, 0.3746066f, 0.3907311f,
895 0.4067366f, 0.4226183f, 0.4383711f, 0.4539905f, 0.4694716f, 0.4848096f,
896 0.5000000f, 0.5150381f, 0.5299193f, 0.5446390f, 0.5591929f, 0.5735764f,
897 0.5877853f, 0.6018150f, 0.6156615f, 0.6293204f, 0.6427876f, 0.6560590f,
898 0.6691306f, 0.6819984f, 0.6946584f, 0.7071068f, 0.7193398f, 0.7313537f,
899 0.7431448f, 0.7547096f, 0.7660444f, 0.7771460f, 0.7880108f, 0.7986355f,
900 0.8090170f, 0.8191520f, 0.8290376f, 0.8386706f, 0.8480481f, 0.8571673f,
901 0.8660254f, 0.8746197f, 0.8829476f, 0.8910065f, 0.8987940f, 0.9063078f,
902 0.9135455f, 0.9205049f, 0.9271839f, 0.9335804f, 0.9396926f, 0.9455186f,
903 0.9510565f, 0.9563048f, 0.9612617f, 0.9659258f, 0.9702957f, 0.9743701f,
904 0.9781476f, 0.9816272f, 0.9848078f, 0.9876883f, 0.9902681f, 0.9925462f,
905 0.9945219f, 0.9961947f, 0.9975641f, 0.9986295f, 0.9993908f, 0.9998477f,
906 1.0000000f
907 };
908
909
910 static void
sincos(int angle,float & cosval,float & sinval)911 sincos( int angle, float& cosval, float& sinval )
912 {
913 angle += (angle < 0 ? 360 : 0);
914 sinval = SinTable[angle];
915 cosval = SinTable[450 - angle];
916 }
917
918 /*
919 constructs polygon that represents elliptic arc.
920 */
ellipse2Poly(Point center,Size axes,int angle,int arcStart,int arcEnd,int delta,CV_OUT std::vector<Point> & pts)921 void ellipse2Poly( Point center, Size axes, int angle,
922 int arcStart, int arcEnd,
923 int delta, CV_OUT std::vector<Point>& pts )
924 {
925 std::vector<Point2d> _pts;
926 ellipse2Poly(Point2d(center.x, center.y), Size2d(axes.width, axes.height), angle,
927 arcStart, arcEnd, delta, _pts);
928 Point prevPt(INT_MIN, INT_MIN);
929 pts.resize(0);
930 for (unsigned int i = 0; i < _pts.size(); ++i)
931 {
932 Point pt;
933 pt.x = cvRound(_pts[i].x);
934 pt.y = cvRound(_pts[i].y);
935 if (pt != prevPt) {
936 pts.push_back(pt);
937 prevPt = pt;
938 }
939 }
940
941 // If there are no points, it's a zero-size polygon
942 if (pts.size() == 1) {
943 pts.assign(2, center);
944 }
945 }
946
ellipse2Poly(Point2d center,Size2d axes,int angle,int arc_start,int arc_end,int delta,std::vector<Point2d> & pts)947 void ellipse2Poly( Point2d center, Size2d axes, int angle,
948 int arc_start, int arc_end,
949 int delta, std::vector<Point2d>& pts )
950 {
951 CV_INSTRUMENT_REGION();
952 CV_Assert(0 < delta && delta <= 180);
953
954 float alpha, beta;
955 int i;
956
957 while( angle < 0 )
958 angle += 360;
959 while( angle > 360 )
960 angle -= 360;
961
962 if( arc_start > arc_end )
963 {
964 i = arc_start;
965 arc_start = arc_end;
966 arc_end = i;
967 }
968 while( arc_start < 0 )
969 {
970 arc_start += 360;
971 arc_end += 360;
972 }
973 while( arc_end > 360 )
974 {
975 arc_end -= 360;
976 arc_start -= 360;
977 }
978 if( arc_end - arc_start > 360 )
979 {
980 arc_start = 0;
981 arc_end = 360;
982 }
983 sincos( angle, alpha, beta );
984 pts.resize(0);
985
986 for( i = arc_start; i < arc_end + delta; i += delta )
987 {
988 double x, y;
989 angle = i;
990 if( angle > arc_end )
991 angle = arc_end;
992 if( angle < 0 )
993 angle += 360;
994
995 x = axes.width * SinTable[450-angle];
996 y = axes.height * SinTable[angle];
997 Point2d pt;
998 pt.x = center.x + x * alpha - y * beta;
999 pt.y = center.y + x * beta + y * alpha;
1000 pts.push_back(pt);
1001 }
1002
1003 // If there are no points, it's a zero-size polygon
1004 if( pts.size() == 1) {
1005 pts.assign(2,center);
1006 }
1007 }
1008
1009
1010 static void
EllipseEx(Mat & img,Point2l center,Size2l axes,int angle,int arc_start,int arc_end,const void * color,int thickness,int line_type)1011 EllipseEx( Mat& img, Point2l center, Size2l axes,
1012 int angle, int arc_start, int arc_end,
1013 const void* color, int thickness, int line_type )
1014 {
1015 axes.width = std::abs(axes.width), axes.height = std::abs(axes.height);
1016 int delta = (int)((std::max(axes.width,axes.height)+(XY_ONE>>1))>>XY_SHIFT);
1017 delta = delta < 3 ? 90 : delta < 10 ? 30 : delta < 15 ? 18 : 5;
1018
1019 std::vector<Point2d> _v;
1020 ellipse2Poly( Point2d((double)center.x, (double)center.y), Size2d((double)axes.width, (double)axes.height), angle, arc_start, arc_end, delta, _v );
1021
1022 std::vector<Point2l> v;
1023 Point2l prevPt(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF);
1024 v.resize(0);
1025 for (unsigned int i = 0; i < _v.size(); ++i)
1026 {
1027 Point2l pt;
1028 pt.x = (int64)cvRound(_v[i].x / XY_ONE) << XY_SHIFT;
1029 pt.y = (int64)cvRound(_v[i].y / XY_ONE) << XY_SHIFT;
1030 pt.x += cvRound(_v[i].x - pt.x);
1031 pt.y += cvRound(_v[i].y - pt.y);
1032 if (pt != prevPt) {
1033 v.push_back(pt);
1034 prevPt = pt;
1035 }
1036 }
1037
1038 // If there are no points, it's a zero-size polygon
1039 if (v.size() == 1) {
1040 v.assign(2, center);
1041 }
1042
1043 if( thickness >= 0 )
1044 PolyLine( img, &v[0], (int)v.size(), false, color, thickness, line_type, XY_SHIFT );
1045 else if( arc_end - arc_start >= 360 )
1046 FillConvexPoly( img, &v[0], (int)v.size(), color, line_type, XY_SHIFT );
1047 else
1048 {
1049 v.push_back(center);
1050 std::vector<PolyEdge> edges;
1051 CollectPolyEdges( img, &v[0], (int)v.size(), edges, color, line_type, XY_SHIFT );
1052 FillEdgeCollection( img, edges, color );
1053 }
1054 }
1055
1056
1057 /****************************************************************************************\
1058 * Polygons filling *
1059 \****************************************************************************************/
1060
ICV_HLINE_X(uchar * ptr,int xl,int xr,const uchar * color,int pix_size)1061 static inline void ICV_HLINE_X(uchar* ptr, int xl, int xr, const uchar* color, int pix_size)
1062 {
1063 uchar* hline_min_ptr = (uchar*)(ptr) + (xl)*(pix_size);
1064 uchar* hline_end_ptr = (uchar*)(ptr) + (xr+1)*(pix_size);
1065 uchar* hline_ptr = hline_min_ptr;
1066 if (pix_size == 1)
1067 memset(hline_min_ptr, *color, hline_end_ptr-hline_min_ptr);
1068 else//if (pix_size != 1)
1069 {
1070 if (hline_min_ptr < hline_end_ptr)
1071 {
1072 memcpy(hline_ptr, color, pix_size);
1073 hline_ptr += pix_size;
1074 }//end if (hline_min_ptr < hline_end_ptr)
1075 size_t sizeToCopy = pix_size;
1076 while(hline_ptr < hline_end_ptr)
1077 {
1078 memcpy(hline_ptr, hline_min_ptr, sizeToCopy);
1079 hline_ptr += sizeToCopy;
1080 sizeToCopy = std::min(2*sizeToCopy, static_cast<size_t>(hline_end_ptr-hline_ptr));
1081 }//end while(hline_ptr < hline_end_ptr)
1082 }//end if (pix_size != 1)
1083 }
1084 //end ICV_HLINE_X()
1085
ICV_HLINE(uchar * ptr,int xl,int xr,const void * color,int pix_size)1086 static inline void ICV_HLINE(uchar* ptr, int xl, int xr, const void* color, int pix_size)
1087 {
1088 ICV_HLINE_X(ptr, xl, xr, reinterpret_cast<const uchar*>(color), pix_size);
1089 }
1090 //end ICV_HLINE()
1091
1092 /* filling convex polygon. v - array of vertices, ntps - number of points */
1093 static void
FillConvexPoly(Mat & img,const Point2l * v,int npts,const void * color,int line_type,int shift)1094 FillConvexPoly( Mat& img, const Point2l* v, int npts, const void* color, int line_type, int shift )
1095 {
1096 struct
1097 {
1098 int idx, di;
1099 int64 x, dx;
1100 int ye;
1101 }
1102 edge[2];
1103
1104 int delta = 1 << shift >> 1;
1105 int i, y, imin = 0;
1106 int edges = npts;
1107 int64 xmin, xmax, ymin, ymax;
1108 uchar* ptr = img.ptr();
1109 Size size = img.size();
1110 int pix_size = (int)img.elemSize();
1111 Point2l p0;
1112 int delta1, delta2;
1113
1114 if( line_type < CV_AA )
1115 delta1 = delta2 = XY_ONE >> 1;
1116 else
1117 delta1 = XY_ONE - 1, delta2 = 0;
1118
1119 p0 = v[npts - 1];
1120 p0.x <<= XY_SHIFT - shift;
1121 p0.y <<= XY_SHIFT - shift;
1122
1123 assert( 0 <= shift && shift <= XY_SHIFT );
1124 xmin = xmax = v[0].x;
1125 ymin = ymax = v[0].y;
1126
1127 for( i = 0; i < npts; i++ )
1128 {
1129 Point2l p = v[i];
1130 if( p.y < ymin )
1131 {
1132 ymin = p.y;
1133 imin = i;
1134 }
1135
1136 ymax = std::max( ymax, p.y );
1137 xmax = std::max( xmax, p.x );
1138 xmin = MIN( xmin, p.x );
1139
1140 p.x <<= XY_SHIFT - shift;
1141 p.y <<= XY_SHIFT - shift;
1142
1143 if( line_type <= 8 )
1144 {
1145 if( shift == 0 )
1146 {
1147 Point pt0, pt1;
1148 pt0.x = (int)(p0.x >> XY_SHIFT);
1149 pt0.y = (int)(p0.y >> XY_SHIFT);
1150 pt1.x = (int)(p.x >> XY_SHIFT);
1151 pt1.y = (int)(p.y >> XY_SHIFT);
1152 Line( img, pt0, pt1, color, line_type );
1153 }
1154 else
1155 Line2( img, p0, p, color );
1156 }
1157 else
1158 LineAA( img, p0, p, color );
1159 p0 = p;
1160 }
1161
1162 xmin = (xmin + delta) >> shift;
1163 xmax = (xmax + delta) >> shift;
1164 ymin = (ymin + delta) >> shift;
1165 ymax = (ymax + delta) >> shift;
1166
1167 if( npts < 3 || (int)xmax < 0 || (int)ymax < 0 || (int)xmin >= size.width || (int)ymin >= size.height )
1168 return;
1169
1170 ymax = MIN( ymax, size.height - 1 );
1171 edge[0].idx = edge[1].idx = imin;
1172
1173 edge[0].ye = edge[1].ye = y = (int)ymin;
1174 edge[0].di = 1;
1175 edge[1].di = npts - 1;
1176
1177 edge[0].x = edge[1].x = -XY_ONE;
1178 edge[0].dx = edge[1].dx = 0;
1179
1180 ptr += img.step*y;
1181
1182 do
1183 {
1184 if( line_type < CV_AA || y < (int)ymax || y == (int)ymin )
1185 {
1186 for( i = 0; i < 2; i++ )
1187 {
1188 if( y >= edge[i].ye )
1189 {
1190 int idx0 = edge[i].idx, di = edge[i].di;
1191 int idx = idx0 + di;
1192 if (idx >= npts) idx -= npts;
1193 int ty = 0;
1194
1195 for (; edges-- > 0; )
1196 {
1197 ty = (int)((v[idx].y + delta) >> shift);
1198 if (ty > y)
1199 {
1200 int64 xs = v[idx0].x;
1201 int64 xe = v[idx].x;
1202 if (shift != XY_SHIFT)
1203 {
1204 xs <<= XY_SHIFT - shift;
1205 xe <<= XY_SHIFT - shift;
1206 }
1207
1208 edge[i].ye = ty;
1209 edge[i].dx = ((xe - xs)*2 + (ty - y)) / (2 * (ty - y));
1210 edge[i].x = xs;
1211 edge[i].idx = idx;
1212 break;
1213 }
1214 idx0 = idx;
1215 idx += di;
1216 if (idx >= npts) idx -= npts;
1217 }
1218 }
1219 }
1220 }
1221
1222 if (edges < 0)
1223 break;
1224
1225 if (y >= 0)
1226 {
1227 int left = 0, right = 1;
1228 if (edge[0].x > edge[1].x)
1229 {
1230 left = 1, right = 0;
1231 }
1232
1233 int xx1 = (int)((edge[left].x + delta1) >> XY_SHIFT);
1234 int xx2 = (int)((edge[right].x + delta2) >> XY_SHIFT);
1235
1236 if( xx2 >= 0 && xx1 < size.width )
1237 {
1238 if( xx1 < 0 )
1239 xx1 = 0;
1240 if( xx2 >= size.width )
1241 xx2 = size.width - 1;
1242 ICV_HLINE( ptr, xx1, xx2, color, pix_size );
1243 }
1244 }
1245 else
1246 {
1247 // TODO optimize scan for negative y
1248 }
1249
1250 edge[0].x += edge[0].dx;
1251 edge[1].x += edge[1].dx;
1252 ptr += img.step;
1253 }
1254 while( ++y <= (int)ymax );
1255 }
1256
1257
1258 /******** Arbitrary polygon **********/
1259
1260 static void
CollectPolyEdges(Mat & img,const Point2l * v,int count,std::vector<PolyEdge> & edges,const void * color,int line_type,int shift,Point offset)1261 CollectPolyEdges( Mat& img, const Point2l* v, int count, std::vector<PolyEdge>& edges,
1262 const void* color, int line_type, int shift, Point offset )
1263 {
1264 int i, delta = offset.y + ((1 << shift) >> 1);
1265 Point2l pt0 = v[count-1], pt1;
1266 pt0.x = (pt0.x + offset.x) << (XY_SHIFT - shift);
1267 pt0.y = (pt0.y + delta) >> shift;
1268
1269 edges.reserve( edges.size() + count );
1270
1271 for( i = 0; i < count; i++, pt0 = pt1 )
1272 {
1273 Point2l t0, t1;
1274 PolyEdge edge;
1275
1276 pt1 = v[i];
1277 pt1.x = (pt1.x + offset.x) << (XY_SHIFT - shift);
1278 pt1.y = (pt1.y + delta) >> shift;
1279
1280 if( line_type < CV_AA )
1281 {
1282 t0.y = pt0.y; t1.y = pt1.y;
1283 t0.x = (pt0.x + (XY_ONE >> 1)) >> XY_SHIFT;
1284 t1.x = (pt1.x + (XY_ONE >> 1)) >> XY_SHIFT;
1285 Line( img, t0, t1, color, line_type );
1286 }
1287 else
1288 {
1289 t0.x = pt0.x; t1.x = pt1.x;
1290 t0.y = pt0.y << XY_SHIFT;
1291 t1.y = pt1.y << XY_SHIFT;
1292 LineAA( img, t0, t1, color );
1293 }
1294
1295 if( pt0.y == pt1.y )
1296 continue;
1297
1298 if( pt0.y < pt1.y )
1299 {
1300 edge.y0 = (int)(pt0.y);
1301 edge.y1 = (int)(pt1.y);
1302 edge.x = pt0.x;
1303 }
1304 else
1305 {
1306 edge.y0 = (int)(pt1.y);
1307 edge.y1 = (int)(pt0.y);
1308 edge.x = pt1.x;
1309 }
1310 edge.dx = (pt1.x - pt0.x) / (pt1.y - pt0.y);
1311 edges.push_back(edge);
1312 }
1313 }
1314
1315 struct CmpEdges
1316 {
operator ()cv::CmpEdges1317 bool operator ()(const PolyEdge& e1, const PolyEdge& e2)
1318 {
1319 return e1.y0 - e2.y0 ? e1.y0 < e2.y0 :
1320 e1.x - e2.x ? e1.x < e2.x : e1.dx < e2.dx;
1321 }
1322 };
1323
1324 /**************** helper macros and functions for sequence/contour processing ***********/
1325
1326 static void
FillEdgeCollection(Mat & img,std::vector<PolyEdge> & edges,const void * color)1327 FillEdgeCollection( Mat& img, std::vector<PolyEdge>& edges, const void* color )
1328 {
1329 PolyEdge tmp;
1330 int i, y, total = (int)edges.size();
1331 Size size = img.size();
1332 PolyEdge* e;
1333 int y_max = INT_MIN, y_min = INT_MAX;
1334 int64 x_max = 0xFFFFFFFFFFFFFFFF, x_min = 0x7FFFFFFFFFFFFFFF;
1335 int pix_size = (int)img.elemSize();
1336
1337 if( total < 2 )
1338 return;
1339
1340 for( i = 0; i < total; i++ )
1341 {
1342 PolyEdge& e1 = edges[i];
1343 assert( e1.y0 < e1.y1 );
1344 // Determine x-coordinate of the end of the edge.
1345 // (This is not necessary x-coordinate of any vertex in the array.)
1346 int64 x1 = e1.x + (e1.y1 - e1.y0) * e1.dx;
1347 y_min = std::min( y_min, e1.y0 );
1348 y_max = std::max( y_max, e1.y1 );
1349 x_min = std::min( x_min, e1.x );
1350 x_max = std::max( x_max, e1.x );
1351 x_min = std::min( x_min, x1 );
1352 x_max = std::max( x_max, x1 );
1353 }
1354
1355 if( y_max < 0 || y_min >= size.height || x_max < 0 || x_min >= ((int64)size.width<<XY_SHIFT) )
1356 return;
1357
1358 std::sort( edges.begin(), edges.end(), CmpEdges() );
1359
1360 // start drawing
1361 tmp.y0 = INT_MAX;
1362 edges.push_back(tmp); // after this point we do not add
1363 // any elements to edges, thus we can use pointers
1364 i = 0;
1365 tmp.next = 0;
1366 e = &edges[i];
1367 y_max = MIN( y_max, size.height );
1368
1369 for( y = e->y0; y < y_max; y++ )
1370 {
1371 PolyEdge *last, *prelast, *keep_prelast;
1372 int sort_flag = 0;
1373 int draw = 0;
1374 int clipline = y < 0;
1375
1376 prelast = &tmp;
1377 last = tmp.next;
1378 while( last || e->y0 == y )
1379 {
1380 if( last && last->y1 == y )
1381 {
1382 // exclude edge if y reaches its lower point
1383 prelast->next = last->next;
1384 last = last->next;
1385 continue;
1386 }
1387 keep_prelast = prelast;
1388 if( last && (e->y0 > y || last->x < e->x) )
1389 {
1390 // go to the next edge in active list
1391 prelast = last;
1392 last = last->next;
1393 }
1394 else if( i < total )
1395 {
1396 // insert new edge into active list if y reaches its upper point
1397 prelast->next = e;
1398 e->next = last;
1399 prelast = e;
1400 e = &edges[++i];
1401 }
1402 else
1403 break;
1404
1405 if( draw )
1406 {
1407 if( !clipline )
1408 {
1409 // convert x's from fixed-point to image coordinates
1410 uchar *timg = img.ptr(y);
1411 int x1, x2;
1412
1413 if (keep_prelast->x > prelast->x)
1414 {
1415 x1 = (int)((prelast->x + XY_ONE - 1) >> XY_SHIFT);
1416 x2 = (int)(keep_prelast->x >> XY_SHIFT);
1417 }
1418 else
1419 {
1420 x1 = (int)((keep_prelast->x + XY_ONE - 1) >> XY_SHIFT);
1421 x2 = (int)(prelast->x >> XY_SHIFT);
1422 }
1423
1424 // clip and draw the line
1425 if( x1 < size.width && x2 >= 0 )
1426 {
1427 if( x1 < 0 )
1428 x1 = 0;
1429 if( x2 >= size.width )
1430 x2 = size.width - 1;
1431 ICV_HLINE( timg, x1, x2, color, pix_size );
1432 }
1433 }
1434 keep_prelast->x += keep_prelast->dx;
1435 prelast->x += prelast->dx;
1436 }
1437 draw ^= 1;
1438 }
1439
1440 // sort edges (using bubble sort)
1441 keep_prelast = 0;
1442
1443 do
1444 {
1445 prelast = &tmp;
1446 last = tmp.next;
1447
1448 while( last != keep_prelast && last->next != 0 )
1449 {
1450 PolyEdge *te = last->next;
1451
1452 // swap edges
1453 if( last->x > te->x )
1454 {
1455 prelast->next = te;
1456 last->next = te->next;
1457 te->next = last;
1458 prelast = te;
1459 sort_flag = 1;
1460 }
1461 else
1462 {
1463 prelast = last;
1464 last = te;
1465 }
1466 }
1467 keep_prelast = prelast;
1468 }
1469 while( sort_flag && keep_prelast != tmp.next && keep_prelast != &tmp );
1470 }
1471 }
1472
1473
1474 /* draws simple or filled circle */
1475 static void
Circle(Mat & img,Point center,int radius,const void * color,int fill)1476 Circle( Mat& img, Point center, int radius, const void* color, int fill )
1477 {
1478 Size size = img.size();
1479 size_t step = img.step;
1480 int pix_size = (int)img.elemSize();
1481 uchar* ptr = img.ptr();
1482 int err = 0, dx = radius, dy = 0, plus = 1, minus = (radius << 1) - 1;
1483 int inside = center.x >= radius && center.x < size.width - radius &&
1484 center.y >= radius && center.y < size.height - radius;
1485
1486 #define ICV_PUT_POINT( ptr, x ) \
1487 memcpy( ptr + (x)*pix_size, color, pix_size );
1488
1489 while( dx >= dy )
1490 {
1491 int mask;
1492 int y11 = center.y - dy, y12 = center.y + dy, y21 = center.y - dx, y22 = center.y + dx;
1493 int x11 = center.x - dx, x12 = center.x + dx, x21 = center.x - dy, x22 = center.x + dy;
1494
1495 if( inside )
1496 {
1497 uchar *tptr0 = ptr + y11 * step;
1498 uchar *tptr1 = ptr + y12 * step;
1499
1500 if( !fill )
1501 {
1502 ICV_PUT_POINT( tptr0, x11 );
1503 ICV_PUT_POINT( tptr1, x11 );
1504 ICV_PUT_POINT( tptr0, x12 );
1505 ICV_PUT_POINT( tptr1, x12 );
1506 }
1507 else
1508 {
1509 ICV_HLINE( tptr0, x11, x12, color, pix_size );
1510 ICV_HLINE( tptr1, x11, x12, color, pix_size );
1511 }
1512
1513 tptr0 = ptr + y21 * step;
1514 tptr1 = ptr + y22 * step;
1515
1516 if( !fill )
1517 {
1518 ICV_PUT_POINT( tptr0, x21 );
1519 ICV_PUT_POINT( tptr1, x21 );
1520 ICV_PUT_POINT( tptr0, x22 );
1521 ICV_PUT_POINT( tptr1, x22 );
1522 }
1523 else
1524 {
1525 ICV_HLINE( tptr0, x21, x22, color, pix_size );
1526 ICV_HLINE( tptr1, x21, x22, color, pix_size );
1527 }
1528 }
1529 else if( x11 < size.width && x12 >= 0 && y21 < size.height && y22 >= 0 )
1530 {
1531 if( fill )
1532 {
1533 x11 = std::max( x11, 0 );
1534 x12 = MIN( x12, size.width - 1 );
1535 }
1536
1537 if( (unsigned)y11 < (unsigned)size.height )
1538 {
1539 uchar *tptr = ptr + y11 * step;
1540
1541 if( !fill )
1542 {
1543 if( x11 >= 0 )
1544 ICV_PUT_POINT( tptr, x11 );
1545 if( x12 < size.width )
1546 ICV_PUT_POINT( tptr, x12 );
1547 }
1548 else
1549 ICV_HLINE( tptr, x11, x12, color, pix_size );
1550 }
1551
1552 if( (unsigned)y12 < (unsigned)size.height )
1553 {
1554 uchar *tptr = ptr + y12 * step;
1555
1556 if( !fill )
1557 {
1558 if( x11 >= 0 )
1559 ICV_PUT_POINT( tptr, x11 );
1560 if( x12 < size.width )
1561 ICV_PUT_POINT( tptr, x12 );
1562 }
1563 else
1564 ICV_HLINE( tptr, x11, x12, color, pix_size );
1565 }
1566
1567 if( x21 < size.width && x22 >= 0 )
1568 {
1569 if( fill )
1570 {
1571 x21 = std::max( x21, 0 );
1572 x22 = MIN( x22, size.width - 1 );
1573 }
1574
1575 if( (unsigned)y21 < (unsigned)size.height )
1576 {
1577 uchar *tptr = ptr + y21 * step;
1578
1579 if( !fill )
1580 {
1581 if( x21 >= 0 )
1582 ICV_PUT_POINT( tptr, x21 );
1583 if( x22 < size.width )
1584 ICV_PUT_POINT( tptr, x22 );
1585 }
1586 else
1587 ICV_HLINE( tptr, x21, x22, color, pix_size );
1588 }
1589
1590 if( (unsigned)y22 < (unsigned)size.height )
1591 {
1592 uchar *tptr = ptr + y22 * step;
1593
1594 if( !fill )
1595 {
1596 if( x21 >= 0 )
1597 ICV_PUT_POINT( tptr, x21 );
1598 if( x22 < size.width )
1599 ICV_PUT_POINT( tptr, x22 );
1600 }
1601 else
1602 ICV_HLINE( tptr, x21, x22, color, pix_size );
1603 }
1604 }
1605 }
1606 dy++;
1607 err += plus;
1608 plus += 2;
1609
1610 mask = (err <= 0) - 1;
1611
1612 err -= minus & mask;
1613 dx += mask;
1614 minus -= mask & 2;
1615 }
1616
1617 #undef ICV_PUT_POINT
1618 }
1619
1620
1621 static void
ThickLine(Mat & img,Point2l p0,Point2l p1,const void * color,int thickness,int line_type,int flags,int shift)1622 ThickLine( Mat& img, Point2l p0, Point2l p1, const void* color,
1623 int thickness, int line_type, int flags, int shift )
1624 {
1625 static const double INV_XY_ONE = 1./XY_ONE;
1626
1627 p0.x <<= XY_SHIFT - shift;
1628 p0.y <<= XY_SHIFT - shift;
1629 p1.x <<= XY_SHIFT - shift;
1630 p1.y <<= XY_SHIFT - shift;
1631
1632 if( thickness <= 1 )
1633 {
1634 if( line_type < CV_AA )
1635 {
1636 if( line_type == 1 || line_type == 4 || shift == 0 )
1637 {
1638 p0.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT;
1639 p0.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT;
1640 p1.x = (p1.x + (XY_ONE>>1)) >> XY_SHIFT;
1641 p1.y = (p1.y + (XY_ONE>>1)) >> XY_SHIFT;
1642 Line( img, p0, p1, color, line_type );
1643 }
1644 else
1645 Line2( img, p0, p1, color );
1646 }
1647 else
1648 LineAA( img, p0, p1, color );
1649 }
1650 else
1651 {
1652 Point2l pt[4], dp = Point2l(0,0);
1653 double dx = (p0.x - p1.x)*INV_XY_ONE, dy = (p1.y - p0.y)*INV_XY_ONE;
1654 double r = dx * dx + dy * dy;
1655 int i, oddThickness = thickness & 1;
1656 thickness <<= XY_SHIFT - 1;
1657
1658 if( fabs(r) > DBL_EPSILON )
1659 {
1660 r = (thickness + oddThickness*XY_ONE*0.5)/std::sqrt(r);
1661 dp.x = cvRound( dy * r );
1662 dp.y = cvRound( dx * r );
1663
1664 pt[0].x = p0.x + dp.x;
1665 pt[0].y = p0.y + dp.y;
1666 pt[1].x = p0.x - dp.x;
1667 pt[1].y = p0.y - dp.y;
1668 pt[2].x = p1.x - dp.x;
1669 pt[2].y = p1.y - dp.y;
1670 pt[3].x = p1.x + dp.x;
1671 pt[3].y = p1.y + dp.y;
1672
1673 FillConvexPoly( img, pt, 4, color, line_type, XY_SHIFT );
1674 }
1675
1676 for( i = 0; i < 2; i++ )
1677 {
1678 if( flags & (i+1) )
1679 {
1680 if( line_type < CV_AA )
1681 {
1682 Point center;
1683 center.x = (int)((p0.x + (XY_ONE>>1)) >> XY_SHIFT);
1684 center.y = (int)((p0.y + (XY_ONE>>1)) >> XY_SHIFT);
1685 Circle( img, center, (thickness + (XY_ONE>>1)) >> XY_SHIFT, color, 1 );
1686 }
1687 else
1688 {
1689 EllipseEx( img, p0, Size2l(thickness, thickness),
1690 0, 0, 360, color, -1, line_type );
1691 }
1692 }
1693 p0 = p1;
1694 }
1695 }
1696 }
1697
1698
1699 static void
PolyLine(Mat & img,const Point2l * v,int count,bool is_closed,const void * color,int thickness,int line_type,int shift)1700 PolyLine( Mat& img, const Point2l* v, int count, bool is_closed,
1701 const void* color, int thickness,
1702 int line_type, int shift )
1703 {
1704 if( !v || count <= 0 )
1705 return;
1706
1707 int i = is_closed ? count - 1 : 0;
1708 int flags = 2 + !is_closed;
1709 Point2l p0;
1710 CV_Assert( 0 <= shift && shift <= XY_SHIFT && thickness >= 0 );
1711
1712 p0 = v[i];
1713 for( i = !is_closed; i < count; i++ )
1714 {
1715 Point2l p = v[i];
1716 ThickLine( img, p0, p, color, thickness, line_type, flags, shift );
1717 p0 = p;
1718 flags = 2;
1719 }
1720 }
1721
1722 /* ----------------------------------------------------------------------------------------- */
1723 /* ADDING A SET OF PREDEFINED MARKERS WHICH COULD BE USED TO HIGHLIGHT POSITIONS IN AN IMAGE */
1724 /* ----------------------------------------------------------------------------------------- */
1725
drawMarker(InputOutputArray img,Point position,const Scalar & color,int markerType,int markerSize,int thickness,int line_type)1726 void drawMarker(InputOutputArray img, Point position, const Scalar& color, int markerType, int markerSize, int thickness, int line_type)
1727 {
1728 switch(markerType)
1729 {
1730 // The cross marker case
1731 case MARKER_CROSS:
1732 line(img, Point(position.x-(markerSize/2), position.y), Point(position.x+(markerSize/2), position.y), color, thickness, line_type);
1733 line(img, Point(position.x, position.y-(markerSize/2)), Point(position.x, position.y+(markerSize/2)), color, thickness, line_type);
1734 break;
1735
1736 // The tilted cross marker case
1737 case MARKER_TILTED_CROSS:
1738 line(img, Point(position.x-(markerSize/2), position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
1739 line(img, Point(position.x+(markerSize/2), position.y-(markerSize/2)), Point(position.x-(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
1740 break;
1741
1742 // The star marker case
1743 case MARKER_STAR:
1744 line(img, Point(position.x-(markerSize/2), position.y), Point(position.x+(markerSize/2), position.y), color, thickness, line_type);
1745 line(img, Point(position.x, position.y-(markerSize/2)), Point(position.x, position.y+(markerSize/2)), color, thickness, line_type);
1746 line(img, Point(position.x-(markerSize/2), position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
1747 line(img, Point(position.x+(markerSize/2), position.y-(markerSize/2)), Point(position.x-(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
1748 break;
1749
1750 // The diamond marker case
1751 case MARKER_DIAMOND:
1752 line(img, Point(position.x, position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y), color, thickness, line_type);
1753 line(img, Point(position.x+(markerSize/2), position.y), Point(position.x, position.y+(markerSize/2)), color, thickness, line_type);
1754 line(img, Point(position.x, position.y+(markerSize/2)), Point(position.x-(markerSize/2), position.y), color, thickness, line_type);
1755 line(img, Point(position.x-(markerSize/2), position.y), Point(position.x, position.y-(markerSize/2)), color, thickness, line_type);
1756 break;
1757
1758 // The square marker case
1759 case MARKER_SQUARE:
1760 line(img, Point(position.x-(markerSize/2), position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y-(markerSize/2)), color, thickness, line_type);
1761 line(img, Point(position.x+(markerSize/2), position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
1762 line(img, Point(position.x+(markerSize/2), position.y+(markerSize/2)), Point(position.x-(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
1763 line(img, Point(position.x-(markerSize/2), position.y+(markerSize/2)), Point(position.x-(markerSize/2), position.y-(markerSize/2)), color, thickness, line_type);
1764 break;
1765
1766 // The triangle up marker case
1767 case MARKER_TRIANGLE_UP:
1768 line(img, Point(position.x-(markerSize/2), position.y+(markerSize/2)), Point(position.x+(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
1769 line(img, Point(position.x+(markerSize/2), position.y+(markerSize/2)), Point(position.x, position.y-(markerSize/2)), color, thickness, line_type);
1770 line(img, Point(position.x, position.y-(markerSize/2)), Point(position.x-(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
1771 break;
1772
1773 // The triangle down marker case
1774 case MARKER_TRIANGLE_DOWN:
1775 line(img, Point(position.x-(markerSize/2), position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y-(markerSize/2)), color, thickness, line_type);
1776 line(img, Point(position.x+(markerSize/2), position.y-(markerSize/2)), Point(position.x, position.y+(markerSize/2)), color, thickness, line_type);
1777 line(img, Point(position.x, position.y+(markerSize/2)), Point(position.x-(markerSize/2), position.y-(markerSize/2)), color, thickness, line_type);
1778 break;
1779
1780 // If any number that doesn't exist is entered as marker type, draw a cross marker, to avoid crashes
1781 default:
1782 drawMarker(img, position, color, MARKER_CROSS, markerSize, thickness, line_type);
1783 break;
1784 }
1785 }
1786
1787 /****************************************************************************************\
1788 * External functions *
1789 \****************************************************************************************/
1790
line(InputOutputArray _img,Point pt1,Point pt2,const Scalar & color,int thickness,int line_type,int shift)1791 void line( InputOutputArray _img, Point pt1, Point pt2, const Scalar& color,
1792 int thickness, int line_type, int shift )
1793 {
1794 CV_INSTRUMENT_REGION();
1795
1796 Mat img = _img.getMat();
1797
1798 if( line_type == CV_AA && img.depth() != CV_8U )
1799 line_type = 8;
1800
1801 CV_Assert( 0 < thickness && thickness <= MAX_THICKNESS );
1802 CV_Assert( 0 <= shift && shift <= XY_SHIFT );
1803
1804 double buf[4];
1805 scalarToRawData( color, buf, img.type(), 0 );
1806 ThickLine( img, pt1, pt2, buf, thickness, line_type, 3, shift );
1807 }
1808
arrowedLine(InputOutputArray img,Point pt1,Point pt2,const Scalar & color,int thickness,int line_type,int shift,double tipLength)1809 void arrowedLine(InputOutputArray img, Point pt1, Point pt2, const Scalar& color,
1810 int thickness, int line_type, int shift, double tipLength)
1811 {
1812 CV_INSTRUMENT_REGION();
1813
1814 const double tipSize = norm(pt1-pt2)*tipLength; // Factor to normalize the size of the tip depending on the length of the arrow
1815
1816 line(img, pt1, pt2, color, thickness, line_type, shift);
1817
1818 const double angle = atan2( (double) pt1.y - pt2.y, (double) pt1.x - pt2.x );
1819
1820 Point p(cvRound(pt2.x + tipSize * cos(angle + CV_PI / 4)),
1821 cvRound(pt2.y + tipSize * sin(angle + CV_PI / 4)));
1822 line(img, p, pt2, color, thickness, line_type, shift);
1823
1824 p.x = cvRound(pt2.x + tipSize * cos(angle - CV_PI / 4));
1825 p.y = cvRound(pt2.y + tipSize * sin(angle - CV_PI / 4));
1826 line(img, p, pt2, color, thickness, line_type, shift);
1827 }
1828
rectangle(InputOutputArray _img,Point pt1,Point pt2,const Scalar & color,int thickness,int lineType,int shift)1829 void rectangle( InputOutputArray _img, Point pt1, Point pt2,
1830 const Scalar& color, int thickness,
1831 int lineType, int shift )
1832 {
1833 CV_INSTRUMENT_REGION();
1834
1835 Mat img = _img.getMat();
1836
1837 if( lineType == CV_AA && img.depth() != CV_8U )
1838 lineType = 8;
1839
1840 CV_Assert( thickness <= MAX_THICKNESS );
1841 CV_Assert( 0 <= shift && shift <= XY_SHIFT );
1842
1843 double buf[4];
1844 scalarToRawData(color, buf, img.type(), 0);
1845
1846 Point2l pt[4];
1847
1848 pt[0] = pt1;
1849 pt[1].x = pt2.x;
1850 pt[1].y = pt1.y;
1851 pt[2] = pt2;
1852 pt[3].x = pt1.x;
1853 pt[3].y = pt2.y;
1854
1855 if( thickness >= 0 )
1856 PolyLine( img, pt, 4, true, buf, thickness, lineType, shift );
1857 else
1858 FillConvexPoly( img, pt, 4, buf, lineType, shift );
1859 }
1860
1861
rectangle(InputOutputArray img,Rect rec,const Scalar & color,int thickness,int lineType,int shift)1862 void rectangle( InputOutputArray img, Rect rec,
1863 const Scalar& color, int thickness,
1864 int lineType, int shift )
1865 {
1866 CV_INSTRUMENT_REGION();
1867
1868 if( !rec.empty() )
1869 rectangle( img, rec.tl(), rec.br() - Point(1<<shift,1<<shift),
1870 color, thickness, lineType, shift );
1871 }
1872
1873
circle(InputOutputArray _img,Point center,int radius,const Scalar & color,int thickness,int line_type,int shift)1874 void circle( InputOutputArray _img, Point center, int radius,
1875 const Scalar& color, int thickness, int line_type, int shift )
1876 {
1877 CV_INSTRUMENT_REGION();
1878
1879 Mat img = _img.getMat();
1880
1881 if( line_type == CV_AA && img.depth() != CV_8U )
1882 line_type = 8;
1883
1884 CV_Assert( radius >= 0 && thickness <= MAX_THICKNESS &&
1885 0 <= shift && shift <= XY_SHIFT );
1886
1887 double buf[4];
1888 scalarToRawData(color, buf, img.type(), 0);
1889
1890 if( thickness > 1 || line_type != LINE_8 || shift > 0 )
1891 {
1892 Point2l _center(center);
1893 int64 _radius(radius);
1894 _center.x <<= XY_SHIFT - shift;
1895 _center.y <<= XY_SHIFT - shift;
1896 _radius <<= XY_SHIFT - shift;
1897 EllipseEx( img, _center, Size2l(_radius, _radius),
1898 0, 0, 360, buf, thickness, line_type );
1899 }
1900 else
1901 Circle( img, center, radius, buf, thickness < 0 );
1902 }
1903
1904
ellipse(InputOutputArray _img,Point center,Size axes,double angle,double start_angle,double end_angle,const Scalar & color,int thickness,int line_type,int shift)1905 void ellipse( InputOutputArray _img, Point center, Size axes,
1906 double angle, double start_angle, double end_angle,
1907 const Scalar& color, int thickness, int line_type, int shift )
1908 {
1909 CV_INSTRUMENT_REGION();
1910
1911 Mat img = _img.getMat();
1912
1913 if( line_type == CV_AA && img.depth() != CV_8U )
1914 line_type = 8;
1915
1916 CV_Assert( axes.width >= 0 && axes.height >= 0 &&
1917 thickness <= MAX_THICKNESS && 0 <= shift && shift <= XY_SHIFT );
1918
1919 double buf[4];
1920 scalarToRawData(color, buf, img.type(), 0);
1921
1922 int _angle = cvRound(angle);
1923 int _start_angle = cvRound(start_angle);
1924 int _end_angle = cvRound(end_angle);
1925 Point2l _center(center);
1926 Size2l _axes(axes);
1927 _center.x <<= XY_SHIFT - shift;
1928 _center.y <<= XY_SHIFT - shift;
1929 _axes.width <<= XY_SHIFT - shift;
1930 _axes.height <<= XY_SHIFT - shift;
1931
1932 EllipseEx( img, _center, _axes, _angle, _start_angle,
1933 _end_angle, buf, thickness, line_type );
1934 }
1935
ellipse(InputOutputArray _img,const RotatedRect & box,const Scalar & color,int thickness,int lineType)1936 void ellipse(InputOutputArray _img, const RotatedRect& box, const Scalar& color,
1937 int thickness, int lineType)
1938 {
1939 CV_INSTRUMENT_REGION();
1940
1941 Mat img = _img.getMat();
1942
1943 if( lineType == CV_AA && img.depth() != CV_8U )
1944 lineType = 8;
1945
1946 CV_Assert( box.size.width >= 0 && box.size.height >= 0 &&
1947 thickness <= MAX_THICKNESS );
1948
1949 double buf[4];
1950 scalarToRawData(color, buf, img.type(), 0);
1951
1952 int _angle = cvRound(box.angle);
1953 Point2l center(cvRound(box.center.x),
1954 cvRound(box.center.y));
1955 center.x = (center.x << XY_SHIFT) + cvRound((box.center.x - center.x)*XY_ONE);
1956 center.y = (center.y << XY_SHIFT) + cvRound((box.center.y - center.y)*XY_ONE);
1957 Size2l axes(cvRound(box.size.width),
1958 cvRound(box.size.height));
1959 axes.width = (axes.width << (XY_SHIFT - 1)) + cvRound((box.size.width - axes.width)*(XY_ONE>>1));
1960 axes.height = (axes.height << (XY_SHIFT - 1)) + cvRound((box.size.height - axes.height)*(XY_ONE>>1));
1961 EllipseEx( img, center, axes, _angle, 0, 360, buf, thickness, lineType );
1962 }
1963
fillConvexPoly(InputOutputArray _img,const Point * pts,int npts,const Scalar & color,int line_type,int shift)1964 void fillConvexPoly( InputOutputArray _img, const Point* pts, int npts,
1965 const Scalar& color, int line_type, int shift )
1966 {
1967 CV_INSTRUMENT_REGION();
1968
1969 Mat img = _img.getMat();
1970
1971 if( !pts || npts <= 0 )
1972 return;
1973
1974 if( line_type == CV_AA && img.depth() != CV_8U )
1975 line_type = 8;
1976
1977 double buf[4];
1978 CV_Assert( 0 <= shift && shift <= XY_SHIFT );
1979 scalarToRawData(color, buf, img.type(), 0);
1980 std::vector<Point2l> _pts(pts, pts + npts);
1981 FillConvexPoly( img, _pts.data(), npts, buf, line_type, shift );
1982 }
1983
fillPoly(InputOutputArray _img,const Point ** pts,const int * npts,int ncontours,const Scalar & color,int line_type,int shift,Point offset)1984 void fillPoly( InputOutputArray _img, const Point** pts, const int* npts, int ncontours,
1985 const Scalar& color, int line_type,
1986 int shift, Point offset )
1987 {
1988 CV_INSTRUMENT_REGION();
1989
1990 Mat img = _img.getMat();
1991
1992 if( line_type == CV_AA && img.depth() != CV_8U )
1993 line_type = 8;
1994
1995 CV_Assert( pts && npts && ncontours >= 0 && 0 <= shift && shift <= XY_SHIFT );
1996
1997 double buf[4];
1998 scalarToRawData(color, buf, img.type(), 0);
1999
2000 std::vector<PolyEdge> edges;
2001
2002 int i, total = 0;
2003 for( i = 0; i < ncontours; i++ )
2004 total += npts[i];
2005
2006 edges.reserve( total + 1 );
2007 for (i = 0; i < ncontours; i++)
2008 {
2009 std::vector<Point2l> _pts(pts[i], pts[i] + npts[i]);
2010 CollectPolyEdges(img, _pts.data(), npts[i], edges, buf, line_type, shift, offset);
2011 }
2012
2013 FillEdgeCollection(img, edges, buf);
2014 }
2015
polylines(InputOutputArray _img,const Point * const * pts,const int * npts,int ncontours,bool isClosed,const Scalar & color,int thickness,int line_type,int shift)2016 void polylines( InputOutputArray _img, const Point* const* pts, const int* npts, int ncontours, bool isClosed,
2017 const Scalar& color, int thickness, int line_type, int shift )
2018 {
2019 CV_INSTRUMENT_REGION();
2020
2021 Mat img = _img.getMat();
2022
2023 if( line_type == CV_AA && img.depth() != CV_8U )
2024 line_type = 8;
2025
2026 CV_Assert( pts && npts && ncontours >= 0 &&
2027 0 <= thickness && thickness <= MAX_THICKNESS &&
2028 0 <= shift && shift <= XY_SHIFT );
2029
2030 double buf[4];
2031 scalarToRawData( color, buf, img.type(), 0 );
2032
2033 for( int i = 0; i < ncontours; i++ )
2034 {
2035 std::vector<Point2l> _pts(pts[i], pts[i]+npts[i]);
2036 PolyLine( img, _pts.data(), npts[i], isClosed, buf, thickness, line_type, shift );
2037 }
2038 }
2039
2040
2041 enum { FONT_SIZE_SHIFT=8, FONT_ITALIC_ALPHA=(1 << 8),
2042 FONT_ITALIC_DIGIT=(2 << 8), FONT_ITALIC_PUNCT=(4 << 8),
2043 FONT_ITALIC_BRACES=(8 << 8), FONT_HAVE_GREEK=(16 << 8),
2044 FONT_HAVE_CYRILLIC=(32 << 8) };
2045
2046 static const int HersheyPlain[] = {
2047 (5 + 4*16) + FONT_HAVE_GREEK,
2048 199, 214, 217, 233, 219, 197, 234, 216, 221, 222, 228, 225, 211, 224, 210, 220,
2049 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 212, 213, 191, 226, 192,
2050 215, 190, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
2051 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 193, 84,
2052 194, 85, 86, 87, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
2053 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
2054 195, 223, 196, 88 };
2055
2056 static const int HersheyPlainItalic[] = {
2057 (5 + 4*16) + FONT_ITALIC_ALPHA + FONT_HAVE_GREEK,
2058 199, 214, 217, 233, 219, 197, 234, 216, 221, 222, 228, 225, 211, 224, 210, 220,
2059 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 212, 213, 191, 226, 192,
2060 215, 190, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
2061 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 193, 84,
2062 194, 85, 86, 87, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
2063 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
2064 195, 223, 196, 88 };
2065
2066 static const int HersheyComplexSmall[] = {
2067 (6 + 7*16) + FONT_HAVE_GREEK,
2068 1199, 1214, 1217, 1275, 1274, 1271, 1272, 1216, 1221, 1222, 1219, 1232, 1211, 1231, 1210, 1220,
2069 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1212, 2213, 1241, 1238, 1242,
2070 1215, 1273, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013,
2071 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1223, 1084,
2072 1224, 1247, 586, 1249, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
2073 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126,
2074 1225, 1229, 1226, 1246 };
2075
2076 static const int HersheyComplexSmallItalic[] = {
2077 (6 + 7*16) + FONT_ITALIC_ALPHA + FONT_HAVE_GREEK,
2078 1199, 1214, 1217, 1275, 1274, 1271, 1272, 1216, 1221, 1222, 1219, 1232, 1211, 1231, 1210, 1220,
2079 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1212, 1213, 1241, 1238, 1242,
2080 1215, 1273, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063,
2081 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1223, 1084,
2082 1224, 1247, 586, 1249, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161,
2083 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176,
2084 1225, 1229, 1226, 1246 };
2085
2086 static const int HersheySimplex[] = {
2087 (9 + 12*16) + FONT_HAVE_GREEK,
2088 2199, 714, 717, 733, 719, 697, 734, 716, 721, 722, 728, 725, 711, 724, 710, 720,
2089 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 712, 713, 691, 726, 692,
2090 715, 690, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513,
2091 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 693, 584,
2092 694, 2247, 586, 2249, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611,
2093 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626,
2094 695, 723, 696, 2246 };
2095
2096 static const int HersheyDuplex[] = {
2097 (9 + 12*16) + FONT_HAVE_GREEK,
2098 2199, 2714, 2728, 2732, 2719, 2733, 2718, 2727, 2721, 2722, 2723, 2725, 2711, 2724, 2710, 2720,
2099 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2712, 2713, 2730, 2726, 2731,
2100 2715, 2734, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513,
2101 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2223, 2084,
2102 2224, 2247, 587, 2249, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611,
2103 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626,
2104 2225, 2229, 2226, 2246 };
2105
2106 static const int HersheyComplex[] = {
2107 (9 + 12*16) + FONT_HAVE_GREEK + FONT_HAVE_CYRILLIC,
2108 2199, 2214, 2217, 2275, 2274, 2271, 2272, 2216, 2221, 2222, 2219, 2232, 2211, 2231, 2210, 2220,
2109 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2212, 2213, 2241, 2238, 2242,
2110 2215, 2273, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013,
2111 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2223, 2084,
2112 2224, 2247, 587, 2249, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111,
2113 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126,
2114 2225, 2229, 2226, 2246, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811,
2115 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826,
2116 2827, 2828, 2829, 2830, 2831, 2832, 2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909,
2117 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924,
2118 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932};
2119
2120 static const int HersheyComplexItalic[] = {
2121 (9 + 12*16) + FONT_ITALIC_ALPHA + FONT_ITALIC_DIGIT + FONT_ITALIC_PUNCT +
2122 FONT_HAVE_GREEK + FONT_HAVE_CYRILLIC,
2123 2199, 2764, 2778, 2782, 2769, 2783, 2768, 2777, 2771, 2772, 2219, 2232, 2211, 2231, 2210, 2220,
2124 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2212, 2213, 2241, 2238, 2242,
2125 2765, 2273, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063,
2126 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2223, 2084,
2127 2224, 2247, 587, 2249, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161,
2128 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176,
2129 2225, 2229, 2226, 2246 };
2130
2131 static const int HersheyTriplex[] = {
2132 (9 + 12*16) + FONT_HAVE_GREEK,
2133 2199, 3214, 3228, 3232, 3219, 3233, 3218, 3227, 3221, 3222, 3223, 3225, 3211, 3224, 3210, 3220,
2134 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3212, 3213, 3230, 3226, 3231,
2135 3215, 3234, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013,
2136 2014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 2223, 2084,
2137 2224, 2247, 587, 2249, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111,
2138 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126,
2139 2225, 2229, 2226, 2246 };
2140
2141 static const int HersheyTriplexItalic[] = {
2142 (9 + 12*16) + FONT_ITALIC_ALPHA + FONT_ITALIC_DIGIT +
2143 FONT_ITALIC_PUNCT + FONT_HAVE_GREEK,
2144 2199, 3264, 3278, 3282, 3269, 3233, 3268, 3277, 3271, 3272, 3223, 3225, 3261, 3224, 3260, 3270,
2145 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3262, 3263, 3230, 3226, 3231,
2146 3265, 3234, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063,
2147 2064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 2223, 2084,
2148 2224, 2247, 587, 2249, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161,
2149 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176,
2150 2225, 2229, 2226, 2246 };
2151
2152 static const int HersheyScriptSimplex[] = {
2153 (9 + 12*16) + FONT_ITALIC_ALPHA + FONT_HAVE_GREEK,
2154 2199, 714, 717, 733, 719, 697, 734, 716, 721, 722, 728, 725, 711, 724, 710, 720,
2155 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 712, 713, 691, 726, 692,
2156 715, 690, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563,
2157 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 693, 584,
2158 694, 2247, 586, 2249, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661,
2159 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676,
2160 695, 723, 696, 2246 };
2161
2162 static const int HersheyScriptComplex[] = {
2163 (9 + 12*16) + FONT_ITALIC_ALPHA + FONT_ITALIC_DIGIT + FONT_ITALIC_PUNCT + FONT_HAVE_GREEK,
2164 2199, 2764, 2778, 2782, 2769, 2783, 2768, 2777, 2771, 2772, 2219, 2232, 2211, 2231, 2210, 2220,
2165 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2212, 2213, 2241, 2238, 2242,
2166 2215, 2273, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562, 2563,
2167 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2223, 2084,
2168 2224, 2247, 586, 2249, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661,
2169 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676,
2170 2225, 2229, 2226, 2246 };
2171
2172
getFontData(int fontFace)2173 static const int* getFontData(int fontFace)
2174 {
2175 bool isItalic = (fontFace & FONT_ITALIC) != 0;
2176 const int* ascii = 0;
2177
2178 switch( fontFace & 15 )
2179 {
2180 case FONT_HERSHEY_SIMPLEX:
2181 ascii = HersheySimplex;
2182 break;
2183 case FONT_HERSHEY_PLAIN:
2184 ascii = !isItalic ? HersheyPlain : HersheyPlainItalic;
2185 break;
2186 case FONT_HERSHEY_DUPLEX:
2187 ascii = HersheyDuplex;
2188 break;
2189 case FONT_HERSHEY_COMPLEX:
2190 ascii = !isItalic ? HersheyComplex : HersheyComplexItalic;
2191 break;
2192 case FONT_HERSHEY_TRIPLEX:
2193 ascii = !isItalic ? HersheyTriplex : HersheyTriplexItalic;
2194 break;
2195 case FONT_HERSHEY_COMPLEX_SMALL:
2196 ascii = !isItalic ? HersheyComplexSmall : HersheyComplexSmallItalic;
2197 break;
2198 case FONT_HERSHEY_SCRIPT_SIMPLEX:
2199 ascii = HersheyScriptSimplex;
2200 break;
2201 case FONT_HERSHEY_SCRIPT_COMPLEX:
2202 ascii = HersheyScriptComplex;
2203 break;
2204 default:
2205 CV_Error( CV_StsOutOfRange, "Unknown font type" );
2206 }
2207 return ascii;
2208 }
2209
readCheck(int & c,int & i,const String & text,int fontFace)2210 inline void readCheck(int &c, int &i, const String &text, int fontFace)
2211 {
2212
2213 int leftBoundary = ' ', rightBoundary = 127;
2214
2215 if(c >= 0x80 && fontFace == FONT_HERSHEY_COMPLEX)
2216 {
2217 if(c == 0xD0 && (uchar)text[i + 1] >= 0x90 && (uchar)text[i + 1] <= 0xBF)
2218 {
2219 c = (uchar)text[++i] - 17;
2220 leftBoundary = 127;
2221 rightBoundary = 175;
2222 }
2223 else if(c == 0xD1 && (uchar)text[i + 1] >= 0x80 && (uchar)text[i + 1] <= 0x8F)
2224 {
2225 c = (uchar)text[++i] + 47;
2226 leftBoundary = 175;
2227 rightBoundary = 191;
2228 }
2229 else
2230 {
2231 if(c >= 0xC0 && text[i+1] != 0) //2 bytes utf
2232 i++;
2233
2234 if(c >= 0xE0 && text[i+1] != 0) //3 bytes utf
2235 i++;
2236
2237 if(c >= 0xF0 && text[i+1] != 0) //4 bytes utf
2238 i++;
2239
2240 if(c >= 0xF8 && text[i+1] != 0) //5 bytes utf
2241 i++;
2242
2243 if(c >= 0xFC && text[i+1] != 0) //6 bytes utf
2244 i++;
2245
2246 c = '?';
2247 }
2248 }
2249
2250 if(c >= rightBoundary || c < leftBoundary)
2251 c = '?';
2252 }
2253
2254 extern const char* g_HersheyGlyphs[];
2255
putText(InputOutputArray _img,const String & text,Point org,int fontFace,double fontScale,Scalar color,int thickness,int line_type,bool bottomLeftOrigin)2256 void putText( InputOutputArray _img, const String& text, Point org,
2257 int fontFace, double fontScale, Scalar color,
2258 int thickness, int line_type, bool bottomLeftOrigin )
2259
2260 {
2261 CV_INSTRUMENT_REGION();
2262
2263 if ( text.empty() )
2264 {
2265 return;
2266 }
2267 Mat img = _img.getMat();
2268 const int* ascii = getFontData(fontFace);
2269
2270 double buf[4];
2271 scalarToRawData(color, buf, img.type(), 0);
2272
2273 int base_line = -(ascii[0] & 15);
2274 int hscale = cvRound(fontScale*XY_ONE), vscale = hscale;
2275
2276 if( line_type == CV_AA && img.depth() != CV_8U )
2277 line_type = 8;
2278
2279 if( bottomLeftOrigin )
2280 vscale = -vscale;
2281
2282 int64 view_x = (int64)org.x << XY_SHIFT;
2283 int64 view_y = ((int64)org.y << XY_SHIFT) + base_line*vscale;
2284 std::vector<Point2l> pts;
2285 pts.reserve(1 << 10);
2286 const char **faces = cv::g_HersheyGlyphs;
2287
2288 for( int i = 0; i < (int)text.size(); i++ )
2289 {
2290 int c = (uchar)text[i];
2291 Point2l p;
2292
2293 readCheck(c, i, text, fontFace);
2294
2295 const char* ptr = faces[ascii[(c-' ')+1]];
2296 p.x = (uchar)ptr[0] - 'R';
2297 p.y = (uchar)ptr[1] - 'R';
2298 int64 dx = p.y*hscale;
2299 view_x -= p.x*hscale;
2300 pts.resize(0);
2301
2302 for( ptr += 2;; )
2303 {
2304 if( *ptr == ' ' || !*ptr )
2305 {
2306 if( pts.size() > 1 )
2307 PolyLine( img, &pts[0], (int)pts.size(), false, buf, thickness, line_type, XY_SHIFT );
2308 if( !*ptr++ )
2309 break;
2310 pts.resize(0);
2311 }
2312 else
2313 {
2314 p.x = (uchar)ptr[0] - 'R';
2315 p.y = (uchar)ptr[1] - 'R';
2316 ptr += 2;
2317 pts.push_back(Point2l(p.x*hscale + view_x, p.y*vscale + view_y));
2318 }
2319 }
2320 view_x += dx;
2321 }
2322 }
2323
getTextSize(const String & text,int fontFace,double fontScale,int thickness,int * _base_line)2324 Size getTextSize( const String& text, int fontFace, double fontScale, int thickness, int* _base_line)
2325 {
2326 Size size;
2327 double view_x = 0;
2328 const char **faces = cv::g_HersheyGlyphs;
2329 const int* ascii = getFontData(fontFace);
2330
2331 int base_line = (ascii[0] & 15);
2332 int cap_line = (ascii[0] >> 4) & 15;
2333 size.height = cvRound((cap_line + base_line)*fontScale + (thickness+1)/2);
2334
2335 for( int i = 0; i < (int)text.size(); i++ )
2336 {
2337 int c = (uchar)text[i];
2338 Point p;
2339
2340 readCheck(c, i, text, fontFace);
2341
2342 const char* ptr = faces[ascii[(c-' ')+1]];
2343 p.x = (uchar)ptr[0] - 'R';
2344 p.y = (uchar)ptr[1] - 'R';
2345 view_x += (p.y - p.x)*fontScale;
2346 }
2347
2348 size.width = cvRound(view_x + thickness);
2349 if( _base_line )
2350 *_base_line = cvRound(base_line*fontScale + thickness*0.5);
2351 return size;
2352 }
2353
getFontScaleFromHeight(const int fontFace,const int pixelHeight,const int thickness)2354 double getFontScaleFromHeight(const int fontFace, const int pixelHeight, const int thickness)
2355 {
2356 // By https://stackoverflow.com/a/27898487/1531708
2357 const int* ascii = getFontData(fontFace);
2358
2359 int base_line = (ascii[0] & 15);
2360 int cap_line = (ascii[0] >> 4) & 15;
2361
2362 return static_cast<double>(pixelHeight - static_cast<double>((thickness + 1)) / 2.0) / static_cast<double>(cap_line + base_line);
2363 }
2364
2365 }
2366
fillConvexPoly(InputOutputArray img,InputArray _points,const Scalar & color,int lineType,int shift)2367 void cv::fillConvexPoly(InputOutputArray img, InputArray _points,
2368 const Scalar& color, int lineType, int shift)
2369 {
2370 CV_INSTRUMENT_REGION();
2371
2372 Mat points = _points.getMat();
2373 CV_Assert(points.checkVector(2, CV_32S) >= 0);
2374 fillConvexPoly(img, points.ptr<Point>(), points.rows*points.cols*points.channels()/2, color, lineType, shift);
2375 }
2376
fillPoly(InputOutputArray img,InputArrayOfArrays pts,const Scalar & color,int lineType,int shift,Point offset)2377 void cv::fillPoly(InputOutputArray img, InputArrayOfArrays pts,
2378 const Scalar& color, int lineType, int shift, Point offset)
2379 {
2380 CV_INSTRUMENT_REGION();
2381
2382 bool manyContours = pts.kind() == _InputArray::STD_VECTOR_VECTOR ||
2383 pts.kind() == _InputArray::STD_VECTOR_MAT;
2384 int i, ncontours = manyContours ? (int)pts.total() : 1;
2385 if( ncontours == 0 )
2386 return;
2387 AutoBuffer<Point*> _ptsptr(ncontours);
2388 AutoBuffer<int> _npts(ncontours);
2389 Point** ptsptr = _ptsptr.data();
2390 int* npts = _npts.data();
2391
2392 for( i = 0; i < ncontours; i++ )
2393 {
2394 Mat p = pts.getMat(manyContours ? i : -1);
2395 CV_Assert(p.checkVector(2, CV_32S) >= 0);
2396 ptsptr[i] = p.ptr<Point>();
2397 npts[i] = p.rows*p.cols*p.channels()/2;
2398 }
2399 fillPoly(img, (const Point**)ptsptr, npts, (int)ncontours, color, lineType, shift, offset);
2400 }
2401
polylines(InputOutputArray img,InputArrayOfArrays pts,bool isClosed,const Scalar & color,int thickness,int lineType,int shift)2402 void cv::polylines(InputOutputArray img, InputArrayOfArrays pts,
2403 bool isClosed, const Scalar& color,
2404 int thickness, int lineType, int shift)
2405 {
2406 CV_INSTRUMENT_REGION();
2407
2408 bool manyContours = pts.kind() == _InputArray::STD_VECTOR_VECTOR ||
2409 pts.kind() == _InputArray::STD_VECTOR_MAT;
2410 int i, ncontours = manyContours ? (int)pts.total() : 1;
2411 if( ncontours == 0 )
2412 return;
2413 AutoBuffer<Point*> _ptsptr(ncontours);
2414 AutoBuffer<int> _npts(ncontours);
2415 Point** ptsptr = _ptsptr.data();
2416 int* npts = _npts.data();
2417
2418 for( i = 0; i < ncontours; i++ )
2419 {
2420 Mat p = pts.getMat(manyContours ? i : -1);
2421 if( p.total() == 0 )
2422 {
2423 ptsptr[i] = NULL;
2424 npts[i] = 0;
2425 continue;
2426 }
2427 CV_Assert(p.checkVector(2, CV_32S) >= 0);
2428 ptsptr[i] = p.ptr<Point>();
2429 npts[i] = p.rows*p.cols*p.channels()/2;
2430 }
2431 polylines(img, (const Point**)ptsptr, npts, (int)ncontours, isClosed, color, thickness, lineType, shift);
2432 }
2433
2434 namespace
2435 {
2436 using namespace cv;
2437
addChildContour(InputArrayOfArrays contours,size_t ncontours,const Vec4i * hierarchy,int i,std::vector<CvSeq> & seq,std::vector<CvSeqBlock> & block)2438 static void addChildContour(InputArrayOfArrays contours,
2439 size_t ncontours,
2440 const Vec4i* hierarchy,
2441 int i, std::vector<CvSeq>& seq,
2442 std::vector<CvSeqBlock>& block)
2443 {
2444 for( ; i >= 0; i = hierarchy[i][0] )
2445 {
2446 Mat ci = contours.getMat(i);
2447 cvMakeSeqHeaderForArray(CV_SEQ_POLYGON, sizeof(CvSeq), sizeof(Point),
2448 !ci.empty() ? (void*)ci.ptr() : 0, (int)ci.total(),
2449 &seq[i], &block[i] );
2450
2451 int h_next = hierarchy[i][0], h_prev = hierarchy[i][1],
2452 v_next = hierarchy[i][2], v_prev = hierarchy[i][3];
2453 seq[i].h_next = (0 <= h_next && h_next < (int)ncontours) ? &seq[h_next] : 0;
2454 seq[i].h_prev = (0 <= h_prev && h_prev < (int)ncontours) ? &seq[h_prev] : 0;
2455 seq[i].v_next = (0 <= v_next && v_next < (int)ncontours) ? &seq[v_next] : 0;
2456 seq[i].v_prev = (0 <= v_prev && v_prev < (int)ncontours) ? &seq[v_prev] : 0;
2457
2458 if( v_next >= 0 )
2459 addChildContour(contours, ncontours, hierarchy, v_next, seq, block);
2460 }
2461 }
2462 }
2463
drawContours(InputOutputArray _image,InputArrayOfArrays _contours,int contourIdx,const Scalar & color,int thickness,int lineType,InputArray _hierarchy,int maxLevel,Point offset)2464 void cv::drawContours( InputOutputArray _image, InputArrayOfArrays _contours,
2465 int contourIdx, const Scalar& color, int thickness,
2466 int lineType, InputArray _hierarchy,
2467 int maxLevel, Point offset )
2468 {
2469 CV_INSTRUMENT_REGION();
2470
2471 Mat image = _image.getMat(), hierarchy = _hierarchy.getMat();
2472 CvMat _cimage = cvMat(image);
2473
2474 size_t ncontours = _contours.total();
2475 size_t i = 0, first = 0, last = ncontours;
2476 std::vector<CvSeq> seq;
2477 std::vector<CvSeqBlock> block;
2478
2479 if( !last )
2480 return;
2481
2482 seq.resize(last);
2483 block.resize(last);
2484
2485 for( i = first; i < last; i++ )
2486 seq[i].first = 0;
2487
2488 if( contourIdx >= 0 )
2489 {
2490 CV_Assert( 0 <= contourIdx && contourIdx < (int)last );
2491 first = contourIdx;
2492 last = contourIdx + 1;
2493 }
2494
2495 for( i = first; i < last; i++ )
2496 {
2497 Mat ci = _contours.getMat((int)i);
2498 if( ci.empty() )
2499 continue;
2500 int npoints = ci.checkVector(2, CV_32S);
2501 CV_Assert( npoints > 0 );
2502 cvMakeSeqHeaderForArray( CV_SEQ_POLYGON, sizeof(CvSeq), sizeof(Point),
2503 ci.ptr(), npoints, &seq[i], &block[i] );
2504 }
2505
2506 if( hierarchy.empty() || maxLevel == 0 )
2507 for( i = first; i < last; i++ )
2508 {
2509 seq[i].h_next = i < last-1 ? &seq[i+1] : 0;
2510 seq[i].h_prev = i > first ? &seq[i-1] : 0;
2511 }
2512 else
2513 {
2514 size_t count = last - first;
2515 CV_Assert(hierarchy.total() == ncontours && hierarchy.type() == CV_32SC4 );
2516 const Vec4i* h = hierarchy.ptr<Vec4i>();
2517
2518 if( count == ncontours )
2519 {
2520 for( i = first; i < last; i++ )
2521 {
2522 int h_next = h[i][0], h_prev = h[i][1],
2523 v_next = h[i][2], v_prev = h[i][3];
2524 seq[i].h_next = (size_t)h_next < count ? &seq[h_next] : 0;
2525 seq[i].h_prev = (size_t)h_prev < count ? &seq[h_prev] : 0;
2526 seq[i].v_next = (size_t)v_next < count ? &seq[v_next] : 0;
2527 seq[i].v_prev = (size_t)v_prev < count ? &seq[v_prev] : 0;
2528 }
2529 }
2530 else
2531 {
2532 int child = h[first][2];
2533 if( child >= 0 )
2534 {
2535 addChildContour(_contours, ncontours, h, child, seq, block);
2536 seq[first].v_next = &seq[child];
2537 }
2538 }
2539 }
2540
2541 cvDrawContours( &_cimage, &seq[first], cvScalar(color), cvScalar(color), contourIdx >= 0 ?
2542 -maxLevel : maxLevel, thickness, lineType, cvPoint(offset) );
2543 }
2544
2545
2546
2547 static const int CodeDeltas[8][2] =
2548 { {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1} };
2549
2550 #define CV_ADJUST_EDGE_COUNT( count, seq ) \
2551 ((count) -= ((count) == (seq)->total && !CV_IS_SEQ_CLOSED(seq)))
2552
2553 CV_IMPL void
cvDrawContours(void * _img,CvSeq * contour,CvScalar _externalColor,CvScalar _holeColor,int maxLevel,int thickness,int line_type,CvPoint _offset)2554 cvDrawContours( void* _img, CvSeq* contour,
2555 CvScalar _externalColor, CvScalar _holeColor,
2556 int maxLevel, int thickness,
2557 int line_type, CvPoint _offset )
2558 {
2559 CvSeq *contour0 = contour, *h_next = 0;
2560 CvTreeNodeIterator iterator;
2561 std::vector<cv::PolyEdge> edges;
2562 std::vector<cv::Point2l> pts;
2563 cv::Scalar externalColor = _externalColor, holeColor = _holeColor;
2564 cv::Mat img = cv::cvarrToMat(_img);
2565 cv::Point offset = _offset;
2566 double ext_buf[4], hole_buf[4];
2567
2568 if( line_type == CV_AA && img.depth() != CV_8U )
2569 line_type = 8;
2570
2571 if( !contour )
2572 return;
2573
2574 CV_Assert( thickness <= MAX_THICKNESS );
2575
2576 scalarToRawData( externalColor, ext_buf, img.type(), 0 );
2577 scalarToRawData( holeColor, hole_buf, img.type(), 0 );
2578
2579 maxLevel = MAX(maxLevel, INT_MIN+2);
2580 maxLevel = MIN(maxLevel, INT_MAX-1);
2581
2582 if( maxLevel < 0 )
2583 {
2584 h_next = contour->h_next;
2585 contour->h_next = 0;
2586 maxLevel = -maxLevel+1;
2587 }
2588
2589 cvInitTreeNodeIterator( &iterator, contour, maxLevel );
2590 while( (contour = (CvSeq*)cvNextTreeNode( &iterator )) != 0 )
2591 {
2592 CvSeqReader reader;
2593 int i, count = contour->total;
2594 int elem_type = CV_MAT_TYPE(contour->flags);
2595 void* clr = (contour->flags & CV_SEQ_FLAG_HOLE) == 0 ? ext_buf : hole_buf;
2596
2597 cvStartReadSeq( contour, &reader, 0 );
2598 CV_Assert(reader.ptr != NULL);
2599 if( thickness < 0 )
2600 pts.resize(0);
2601
2602 if( CV_IS_SEQ_CHAIN_CONTOUR( contour ))
2603 {
2604 cv::Point pt = ((CvChain*)contour)->origin;
2605 cv::Point prev_pt = pt;
2606 char prev_code = reader.ptr ? reader.ptr[0] : '\0';
2607
2608 prev_pt += offset;
2609
2610 for( i = 0; i < count; i++ )
2611 {
2612 char code;
2613 CV_READ_SEQ_ELEM( code, reader );
2614
2615 assert( (code & ~7) == 0 );
2616
2617 if( code != prev_code )
2618 {
2619 prev_code = code;
2620 if( thickness >= 0 )
2621 cv::ThickLine( img, prev_pt, pt, clr, thickness, line_type, 2, 0 );
2622 else
2623 pts.push_back(pt);
2624 prev_pt = pt;
2625 }
2626
2627 pt.x += CodeDeltas[(int)code][0];
2628 pt.y += CodeDeltas[(int)code][1];
2629 }
2630
2631 if( thickness >= 0 )
2632 cv::ThickLine( img, prev_pt,
2633 cv::Point(((CvChain*)contour)->origin) + offset,
2634 clr, thickness, line_type, 2, 0 );
2635 else
2636 cv::CollectPolyEdges(img, &pts[0], (int)pts.size(),
2637 edges, ext_buf, line_type, 0, offset);
2638 }
2639 else if( CV_IS_SEQ_POLYLINE( contour ))
2640 {
2641 CV_Assert( elem_type == CV_32SC2 );
2642 cv::Point pt1, pt2;
2643 int shift = 0;
2644
2645 count -= !CV_IS_SEQ_CLOSED(contour);
2646 { CvPoint pt_ = CV_STRUCT_INITIALIZER; CV_READ_SEQ_ELEM(pt_, reader); pt1 = pt_; }
2647 pt1 += offset;
2648 if( thickness < 0 )
2649 pts.push_back(pt1);
2650
2651 for( i = 0; i < count; i++ )
2652 {
2653 { CvPoint pt_ = CV_STRUCT_INITIALIZER; CV_READ_SEQ_ELEM(pt_, reader); pt2 = pt_; }
2654 pt2 += offset;
2655 if( thickness >= 0 )
2656 cv::ThickLine( img, pt1, pt2, clr, thickness, line_type, 2, shift );
2657 else
2658 pts.push_back(pt2);
2659 pt1 = pt2;
2660 }
2661 if( thickness < 0 )
2662 cv::CollectPolyEdges( img, &pts[0], (int)pts.size(),
2663 edges, ext_buf, line_type, 0, cv::Point() );
2664 }
2665 }
2666
2667 if( thickness < 0 )
2668 cv::FillEdgeCollection( img, edges, ext_buf );
2669
2670 if( h_next && contour0 )
2671 contour0->h_next = h_next;
2672 }
2673
2674 CV_IMPL int
cvClipLine(CvSize size,CvPoint * pt1,CvPoint * pt2)2675 cvClipLine( CvSize size, CvPoint* pt1, CvPoint* pt2 )
2676 {
2677 CV_Assert( pt1 && pt2 );
2678 return cv::clipLine( size, *(cv::Point*)pt1, *(cv::Point*)pt2 );
2679 }
2680
2681
2682 CV_IMPL int
cvEllipse2Poly(CvPoint center,CvSize axes,int angle,int arc_start,int arc_end,CvPoint * _pts,int delta)2683 cvEllipse2Poly( CvPoint center, CvSize axes, int angle,
2684 int arc_start, int arc_end, CvPoint* _pts, int delta )
2685 {
2686 std::vector<cv::Point> pts;
2687 cv::ellipse2Poly( Point(center), Size(axes), angle, arc_start, arc_end, delta, pts );
2688 memcpy( _pts, &pts[0], pts.size()*sizeof(_pts[0]) );
2689 return (int)pts.size();
2690 }
2691
2692 CV_IMPL CvScalar
cvColorToScalar(double packed_color,int type)2693 cvColorToScalar( double packed_color, int type )
2694 {
2695 cv::Scalar scalar;
2696
2697 if( CV_MAT_DEPTH( type ) == CV_8U )
2698 {
2699 int icolor = cvRound( packed_color );
2700 if( CV_MAT_CN( type ) > 1 )
2701 {
2702 scalar.val[0] = icolor & 255;
2703 scalar.val[1] = (icolor >> 8) & 255;
2704 scalar.val[2] = (icolor >> 16) & 255;
2705 scalar.val[3] = (icolor >> 24) & 255;
2706 }
2707 else
2708 {
2709 scalar.val[0] = cv::saturate_cast<uchar>( icolor );
2710 scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
2711 }
2712 }
2713 else if( CV_MAT_DEPTH( type ) == CV_8S )
2714 {
2715 int icolor = cvRound( packed_color );
2716 if( CV_MAT_CN( type ) > 1 )
2717 {
2718 scalar.val[0] = (char)icolor;
2719 scalar.val[1] = (char)(icolor >> 8);
2720 scalar.val[2] = (char)(icolor >> 16);
2721 scalar.val[3] = (char)(icolor >> 24);
2722 }
2723 else
2724 {
2725 scalar.val[0] = cv::saturate_cast<schar>( icolor );
2726 scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
2727 }
2728 }
2729 else
2730 {
2731 int cn = CV_MAT_CN( type );
2732 switch( cn )
2733 {
2734 case 1:
2735 scalar.val[0] = packed_color;
2736 scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
2737 break;
2738 case 2:
2739 scalar.val[0] = scalar.val[1] = packed_color;
2740 scalar.val[2] = scalar.val[3] = 0;
2741 break;
2742 case 3:
2743 scalar.val[0] = scalar.val[1] = scalar.val[2] = packed_color;
2744 scalar.val[3] = 0;
2745 break;
2746 default:
2747 scalar.val[0] = scalar.val[1] =
2748 scalar.val[2] = scalar.val[3] = packed_color;
2749 break;
2750 }
2751 }
2752
2753 return cvScalar(scalar);
2754 }
2755
2756 CV_IMPL int
cvInitLineIterator(const CvArr * img,CvPoint pt1,CvPoint pt2,CvLineIterator * iterator,int connectivity,int left_to_right)2757 cvInitLineIterator( const CvArr* img, CvPoint pt1, CvPoint pt2,
2758 CvLineIterator* iterator, int connectivity,
2759 int left_to_right )
2760 {
2761 CV_Assert( iterator != 0 );
2762 cv::LineIterator li(cv::cvarrToMat(img), pt1, pt2, connectivity, left_to_right!=0);
2763
2764 iterator->err = li.err;
2765 iterator->minus_delta = li.minusDelta;
2766 iterator->plus_delta = li.plusDelta;
2767 iterator->minus_step = li.minusStep;
2768 iterator->plus_step = li.plusStep;
2769 iterator->ptr = li.ptr;
2770
2771 return li.count;
2772 }
2773
2774 CV_IMPL void
cvLine(CvArr * _img,CvPoint pt1,CvPoint pt2,CvScalar color,int thickness,int line_type,int shift)2775 cvLine( CvArr* _img, CvPoint pt1, CvPoint pt2, CvScalar color,
2776 int thickness, int line_type, int shift )
2777 {
2778 cv::Mat img = cv::cvarrToMat(_img);
2779 cv::line( img, pt1, pt2, color, thickness, line_type, shift );
2780 }
2781
2782 CV_IMPL void
cvRectangle(CvArr * _img,CvPoint pt1,CvPoint pt2,CvScalar color,int thickness,int line_type,int shift)2783 cvRectangle( CvArr* _img, CvPoint pt1, CvPoint pt2,
2784 CvScalar color, int thickness,
2785 int line_type, int shift )
2786 {
2787 cv::Mat img = cv::cvarrToMat(_img);
2788 cv::rectangle( img, pt1, pt2, color, thickness, line_type, shift );
2789 }
2790
2791 CV_IMPL void
cvRectangleR(CvArr * _img,CvRect rec,CvScalar color,int thickness,int line_type,int shift)2792 cvRectangleR( CvArr* _img, CvRect rec,
2793 CvScalar color, int thickness,
2794 int line_type, int shift )
2795 {
2796 cv::Mat img = cv::cvarrToMat(_img);
2797 cv::rectangle( img, rec, color, thickness, line_type, shift );
2798 }
2799
2800 CV_IMPL void
cvCircle(CvArr * _img,CvPoint center,int radius,CvScalar color,int thickness,int line_type,int shift)2801 cvCircle( CvArr* _img, CvPoint center, int radius,
2802 CvScalar color, int thickness, int line_type, int shift )
2803 {
2804 cv::Mat img = cv::cvarrToMat(_img);
2805 cv::circle( img, center, radius, color, thickness, line_type, shift );
2806 }
2807
2808 CV_IMPL void
cvEllipse(CvArr * _img,CvPoint center,CvSize axes,double angle,double start_angle,double end_angle,CvScalar color,int thickness,int line_type,int shift)2809 cvEllipse( CvArr* _img, CvPoint center, CvSize axes,
2810 double angle, double start_angle, double end_angle,
2811 CvScalar color, int thickness, int line_type, int shift )
2812 {
2813 cv::Mat img = cv::cvarrToMat(_img);
2814 cv::ellipse( img, center, axes, angle, start_angle, end_angle,
2815 color, thickness, line_type, shift );
2816 }
2817
2818 CV_IMPL void
cvFillConvexPoly(CvArr * _img,const CvPoint * pts,int npts,CvScalar color,int line_type,int shift)2819 cvFillConvexPoly( CvArr* _img, const CvPoint *pts, int npts,
2820 CvScalar color, int line_type, int shift )
2821 {
2822 cv::Mat img = cv::cvarrToMat(_img);
2823 cv::fillConvexPoly( img, (const cv::Point*)pts, npts,
2824 color, line_type, shift );
2825 }
2826
2827 CV_IMPL void
cvFillPoly(CvArr * _img,CvPoint ** pts,const int * npts,int ncontours,CvScalar color,int line_type,int shift)2828 cvFillPoly( CvArr* _img, CvPoint **pts, const int *npts, int ncontours,
2829 CvScalar color, int line_type, int shift )
2830 {
2831 cv::Mat img = cv::cvarrToMat(_img);
2832
2833 cv::fillPoly( img, (const cv::Point**)pts, npts, ncontours, color, line_type, shift );
2834 }
2835
2836 CV_IMPL void
cvPolyLine(CvArr * _img,CvPoint ** pts,const int * npts,int ncontours,int closed,CvScalar color,int thickness,int line_type,int shift)2837 cvPolyLine( CvArr* _img, CvPoint **pts, const int *npts,
2838 int ncontours, int closed, CvScalar color,
2839 int thickness, int line_type, int shift )
2840 {
2841 cv::Mat img = cv::cvarrToMat(_img);
2842
2843 cv::polylines( img, (const cv::Point**)pts, npts, ncontours,
2844 closed != 0, color, thickness, line_type, shift );
2845 }
2846
2847 CV_IMPL void
cvPutText(CvArr * _img,const char * text,CvPoint org,const CvFont * _font,CvScalar color)2848 cvPutText( CvArr* _img, const char *text, CvPoint org, const CvFont *_font, CvScalar color )
2849 {
2850 cv::Mat img = cv::cvarrToMat(_img);
2851 CV_Assert( text != 0 && _font != 0);
2852 cv::putText( img, text, org, _font->font_face, (_font->hscale+_font->vscale)*0.5,
2853 color, _font->thickness, _font->line_type,
2854 CV_IS_IMAGE(_img) && ((IplImage*)_img)->origin != 0 );
2855 }
2856
2857
2858 CV_IMPL void
cvInitFont(CvFont * font,int font_face,double hscale,double vscale,double shear,int thickness,int line_type)2859 cvInitFont( CvFont *font, int font_face, double hscale, double vscale,
2860 double shear, int thickness, int line_type )
2861 {
2862 CV_Assert( font != 0 && hscale > 0 && vscale > 0 && thickness >= 0 );
2863
2864 font->ascii = cv::getFontData(font_face);
2865 font->font_face = font_face;
2866 font->hscale = (float)hscale;
2867 font->vscale = (float)vscale;
2868 font->thickness = thickness;
2869 font->shear = (float)shear;
2870 font->greek = font->cyrillic = 0;
2871 font->line_type = line_type;
2872 }
2873
2874 CV_IMPL void
cvGetTextSize(const char * text,const CvFont * _font,CvSize * _size,int * _base_line)2875 cvGetTextSize( const char *text, const CvFont *_font, CvSize *_size, int *_base_line )
2876 {
2877 CV_Assert(text != 0 && _font != 0);
2878 cv::Size size = cv::getTextSize( text, _font->font_face, (_font->hscale + _font->vscale)*0.5,
2879 _font->thickness, _base_line );
2880 if( _size )
2881 *_size = cvSize(size);
2882 }
2883
2884 /* End of file. */
2885