1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
41 #include "precomp.hpp"
46 enum { XY_SHIFT = 16, XY_ONE = 1 << XY_SHIFT, DRAWING_STORAGE_BLOCK = (1<<12) - 256 };
48 static const int MAX_THICKNESS = 32767;
52 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) {}
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() );
66 FillEdgeCollection( Mat& img, std::vector<PolyEdge>& edges, const void* color );
69 PolyLine( Mat& img, const Point2l* v, int npts, bool closed,
70 const void* color, int thickness, int line_type, int shift );
73 FillConvexPoly( Mat& img, const Point2l* v, int npts,
74 const void* color, int line_type, int shift );
76 /****************************************************************************************\
78 \****************************************************************************************/
80 bool clipLine( Size img_size, Point& pt1, Point& pt2 )
84 bool inside = clipLine(Size2l(img_size.width, img_size.height), p1, p2);
92 bool clipLine( Size2l img_size, Point2l& pt1, Point2l& pt2 )
94 CV_INSTRUMENT_REGION()
97 int64 right = img_size.width-1, bottom = img_size.height-1;
99 if( img_size.width <= 0 || img_size.height <= 0 )
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;
106 if( (c1 & c2) == 0 && (c1 | c2) != 0 )
111 a = c1 < 8 ? 0 : bottom;
112 x1 += (int64)((double)(a - y1) * (x2 - x1) / (y2 - y1));
114 c1 = (x1 < 0) + (x1 > right) * 2;
118 a = c2 < 8 ? 0 : bottom;
119 x2 += (int64)((double)(a - y2) * (x2 - x1) / (y2 - y1));
121 c2 = (x2 < 0) + (x2 > right) * 2;
123 if( (c1 & c2) == 0 && (c1 | c2) != 0 )
127 a = c1 == 1 ? 0 : right;
128 y1 += (int64)((double)(a - x1) * (y2 - y1) / (x2 - x1));
134 a = c2 == 1 ? 0 : right;
135 y2 += (int64)((double)(a - x2) * (y2 - y1) / (x2 - x1));
141 assert( (c1 & c2) != 0 || (x1 | y1 | x2 | y2) >= 0 );
144 return (c1 | c2) == 0;
147 bool clipLine( Rect img_rect, Point& pt1, Point& pt2 )
149 CV_INSTRUMENT_REGION()
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;
160 Initializes line iterator.
161 Returns number of points on the line or negative number if error.
163 LineIterator::LineIterator(const Mat& img, Point pt1, Point pt2,
164 int connectivity, bool left_to_right)
168 CV_Assert( connectivity == 8 || connectivity == 4 );
170 if( (unsigned)pt1.x >= (unsigned)(img.cols) ||
171 (unsigned)pt2.x >= (unsigned)(img.cols) ||
172 (unsigned)pt1.y >= (unsigned)(img.rows) ||
173 (unsigned)pt2.y >= (unsigned)(img.rows) )
175 if( !clipLine( img.size(), pt1, pt2 ) )
178 err = plusDelta = minusDelta = plusStep = minusStep = count = 0;
186 size_t bt_pix0 = img.elemSize(), bt_pix = bt_pix0;
187 size_t istep = img.step;
189 int dx = pt2.x - pt1.x;
190 int dy = pt2.y - pt1.y;
191 int s = dx < 0 ? -1 : 0;
197 pt1.x ^= (pt1.x ^ pt2.x) & s;
198 pt1.y ^= (pt1.y ^ pt2.y) & s;
203 bt_pix = (bt_pix ^ s) - s;
206 ptr = (uchar*)(img.data + pt1.y * istep + pt1.x * bt_pix0);
210 istep = (istep ^ s) - s;
212 s = dy > dx ? -1 : 0;
214 /* conditional swaps */
223 if( connectivity == 8 )
225 assert( dx >= 0 && dy >= 0 );
227 err = dx - (dy + dy);
229 minusDelta = -(dy + dy);
230 plusStep = (int)istep;
231 minusStep = (int)bt_pix;
234 else /* connectivity == 4 */
236 assert( dx >= 0 && dy >= 0 );
239 plusDelta = (dx + dx) + (dy + dy);
240 minusDelta = -(dy + dy);
241 plusStep = (int)(istep - bt_pix);
242 minusStep = (int)bt_pix;
246 this->ptr0 = img.ptr();
247 this->step = (int)img.step;
248 this->elemSize = (int)bt_pix0;
252 Line( Mat& img, Point pt1, Point pt2,
253 const void* _color, int connectivity = 8 )
255 if( connectivity == 0 )
257 else if( connectivity == 1 )
260 LineIterator iterator(img, pt1, pt2, connectivity, true);
261 int i, count = iterator.count;
262 int pix_size = (int)img.elemSize();
263 const uchar* color = (const uchar*)_color;
265 for( i = 0; i < count; i++, ++iterator )
267 uchar* ptr = *iterator;
270 else if( pix_size == 3 )
277 memcpy( *iterator, color, pix_size );
282 /* Correction table depent on the slope */
283 static const uchar SlopeCorrTable[] = {
284 181, 181, 181, 182, 182, 183, 184, 185, 187, 188, 190, 192, 194, 196, 198, 201,
285 203, 206, 209, 211, 214, 218, 221, 224, 227, 231, 235, 238, 242, 246, 250, 254
288 /* Gaussian for antialiasing filter */
289 static const int FilterTable[] = {
290 168, 177, 185, 194, 202, 210, 218, 224, 231, 236, 241, 246, 249, 252, 254, 254,
291 254, 254, 252, 249, 246, 241, 236, 231, 224, 218, 210, 202, 194, 185, 177, 168,
292 158, 149, 140, 131, 122, 114, 105, 97, 89, 82, 75, 68, 62, 56, 50, 45,
293 40, 36, 32, 28, 25, 22, 19, 16, 14, 12, 11, 9, 8, 7, 5, 5
297 LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color )
300 int ecount, scount = 0;
303 int64 x_step, y_step;
306 int cb = ((uchar*)color)[0], cg = ((uchar*)color)[1], cr = ((uchar*)color)[2], ca = ((uchar*)color)[3];
307 int _cb, _cg, _cr, _ca;
308 int nch = img.channels();
309 uchar* ptr = img.ptr();
310 size_t step = img.step;
311 Size2l size(img.size());
313 if( !((nch == 1 || nch == 3 || nch == 4) && img.depth() == CV_8U) )
315 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);
323 ptr += img.step*2 + 2*nch;
325 size.width = ((size.width - 5) << XY_SHIFT) + 1;
326 size.height = ((size.height - 5) << XY_SHIFT) + 1;
328 if( !clipLine( size, pt1, pt2 ))
351 y_step = (dy << XY_SHIFT) / (ax | 1);
353 ecount = (int)((pt2.x >> XY_SHIFT) - (pt1.x >> XY_SHIFT));
354 j = -(pt1.x & (XY_ONE - 1));
355 pt1.y += ((y_step * j) >> XY_SHIFT) + (XY_ONE >> 1);
356 slope = (y_step >> (XY_SHIFT - 5)) & 0x3f;
357 slope ^= (y_step < 0 ? 0x3f : 0);
359 /* Get 4-bit fractions for end-point adjustments */
360 i = (pt1.x >> (XY_SHIFT - 7)) & 0x78;
361 j = (pt2.x >> (XY_SHIFT - 7)) & 0x78;
374 x_step = (dx << XY_SHIFT) / (ay | 1);
377 ecount = (int)((pt2.y >> XY_SHIFT) - (pt1.y >> XY_SHIFT));
378 j = -(pt1.y & (XY_ONE - 1));
379 pt1.x += ((x_step * j) >> XY_SHIFT) + (XY_ONE >> 1);
380 slope = (x_step >> (XY_SHIFT - 5)) & 0x3f;
381 slope ^= (x_step < 0 ? 0x3f : 0);
383 /* Get 4-bit fractions for end-point adjustments */
384 i = (pt1.y >> (XY_SHIFT - 7)) & 0x78;
385 j = (pt2.y >> (XY_SHIFT - 7)) & 0x78;
388 slope = (slope & 0x20) ? 0x100 : SlopeCorrTable[slope];
390 /* Calc end point correction table */
393 int t1 = ((0x78 - (int)i) | 4) * slope;
394 int t2 = ((int)j | 4) * slope;
398 ep_table[1] = ep_table[3] = ((((j - i) & 0x78) | 4) * slope >> 8) & 0x1ff;
399 ep_table[2] = (t1 >> 8) & 0x1ff;
400 ep_table[4] = ((((j - i) + 0x80) | 4) * slope >> 8) & 0x1ff;
401 ep_table[5] = ((t1 + t0) >> 8) & 0x1ff;
402 ep_table[6] = (t2 >> 8) & 0x1ff;
403 ep_table[7] = ((t2 + t0) >> 8) & 0x1ff;
408 #define ICV_PUT_POINT() \
411 _cb += ((cb - _cb)*a + 127)>> 8;\
413 _cg += ((cg - _cg)*a + 127)>> 8;\
415 _cr += ((cr - _cr)*a + 127)>> 8;\
416 tptr[0] = (uchar)_cb; \
417 tptr[1] = (uchar)_cg; \
418 tptr[2] = (uchar)_cr; \
422 ptr += (pt1.x >> XY_SHIFT) * 3;
426 uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step;
428 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
429 (((ecount >= 2) + 1) & (ecount | 2))];
430 int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
432 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
437 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
442 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
454 ptr += (pt1.y >> XY_SHIFT) * step;
458 uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1) * 3;
460 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
461 (((ecount >= 2) + 1) & (ecount | 2))];
462 int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
464 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
469 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
474 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
488 #define ICV_PUT_POINT() \
491 _cb += ((cb - _cb)*a + 127)>> 8;\
492 tptr[0] = (uchar)_cb; \
497 ptr += (pt1.x >> XY_SHIFT);
501 uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step;
503 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
504 (((ecount >= 2) + 1) & (ecount | 2))];
505 int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
507 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
512 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
517 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
529 ptr += (pt1.y >> XY_SHIFT) * step;
533 uchar *tptr = ptr + ((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;
539 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
544 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
549 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
563 #define ICV_PUT_POINT() \
566 _cb += ((cb - _cb)*a + 127)>> 8;\
568 _cg += ((cg - _cg)*a + 127)>> 8;\
570 _cr += ((cr - _cr)*a + 127)>> 8;\
572 _ca += ((ca - _ca)*a + 127)>> 8;\
573 tptr[0] = (uchar)_cb; \
574 tptr[1] = (uchar)_cg; \
575 tptr[2] = (uchar)_cr; \
576 tptr[3] = (uchar)_ca; \
580 ptr += (pt1.x >> XY_SHIFT) * 4;
584 uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step;
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;
590 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
595 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
600 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
612 ptr += (pt1.y >> XY_SHIFT) * step;
616 uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1) * 4;
618 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
619 (((ecount >= 2) + 1) & (ecount | 2))];
620 int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
622 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
627 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
632 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
648 Line2( Mat& img, Point2l pt1, Point2l pt2, const void* color)
655 int64 x_step, y_step;
656 int cb = ((uchar*)color)[0];
657 int cg = ((uchar*)color)[1];
658 int cr = ((uchar*)color)[2];
659 int pix_size = (int)img.elemSize();
660 uchar *ptr = img.ptr(), *tptr;
661 size_t step = img.step;
662 Size size = img.size();
664 //assert( img && (nch == 1 || nch == 3) && img.depth() == CV_8U );
666 Size2l sizeScaled(((int64)size.width) << XY_SHIFT, ((int64)size.height) << XY_SHIFT);
667 if( !clipLine( sizeScaled, pt1, pt2 ))
690 y_step = (dy << XY_SHIFT) / (ax | 1);
691 ecount = (int)((pt2.x - pt1.x) >> XY_SHIFT);
704 x_step = (dx << XY_SHIFT) / (ay | 1);
706 ecount = (int)((pt2.y - pt1.y) >> XY_SHIFT);
709 pt1.x += (XY_ONE >> 1);
710 pt1.y += (XY_ONE >> 1);
714 #define ICV_PUT_POINT(_x,_y) \
715 x = (_x); y = (_y); \
716 if( 0 <= x && x < size.width && \
717 0 <= y && y < size.height ) \
719 tptr = ptr + y*step + x*3; \
720 tptr[0] = (uchar)cb; \
721 tptr[1] = (uchar)cg; \
722 tptr[2] = (uchar)cr; \
725 ICV_PUT_POINT((int)((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT),
726 (int)((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT));
734 ICV_PUT_POINT((int)(pt1.x), (int)(pt1.y >> XY_SHIFT));
746 ICV_PUT_POINT((int)(pt1.x >> XY_SHIFT), (int)(pt1.y));
755 else if( pix_size == 1 )
757 #define ICV_PUT_POINT(_x,_y) \
758 x = (_x); y = (_y); \
759 if( 0 <= x && x < size.width && \
760 0 <= y && y < size.height ) \
762 tptr = ptr + y*step + x;\
763 tptr[0] = (uchar)cb; \
766 ICV_PUT_POINT((int)((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT),
767 (int)((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT));
775 ICV_PUT_POINT((int)(pt1.x), (int)(pt1.y >> XY_SHIFT));
787 ICV_PUT_POINT((int)(pt1.x >> XY_SHIFT), (int)(pt1.y));
798 #define ICV_PUT_POINT(_x,_y) \
799 x = (_x); y = (_y); \
800 if( 0 <= x && x < size.width && \
801 0 <= y && y < size.height ) \
803 tptr = ptr + y*step + x*pix_size;\
804 for( j = 0; j < pix_size; j++ ) \
805 tptr[j] = ((uchar*)color)[j]; \
808 ICV_PUT_POINT((int)((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT),
809 (int)((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT));
817 ICV_PUT_POINT((int)(pt1.x), (int)(pt1.y >> XY_SHIFT));
829 ICV_PUT_POINT((int)(pt1.x >> XY_SHIFT), (int)(pt1.y));
841 /****************************************************************************************\
842 * Antialiazed Elliptic Arcs via Antialiazed Lines *
843 \****************************************************************************************/
845 static const float SinTable[] =
846 { 0.0000000f, 0.0174524f, 0.0348995f, 0.0523360f, 0.0697565f, 0.0871557f,
847 0.1045285f, 0.1218693f, 0.1391731f, 0.1564345f, 0.1736482f, 0.1908090f,
848 0.2079117f, 0.2249511f, 0.2419219f, 0.2588190f, 0.2756374f, 0.2923717f,
849 0.3090170f, 0.3255682f, 0.3420201f, 0.3583679f, 0.3746066f, 0.3907311f,
850 0.4067366f, 0.4226183f, 0.4383711f, 0.4539905f, 0.4694716f, 0.4848096f,
851 0.5000000f, 0.5150381f, 0.5299193f, 0.5446390f, 0.5591929f, 0.5735764f,
852 0.5877853f, 0.6018150f, 0.6156615f, 0.6293204f, 0.6427876f, 0.6560590f,
853 0.6691306f, 0.6819984f, 0.6946584f, 0.7071068f, 0.7193398f, 0.7313537f,
854 0.7431448f, 0.7547096f, 0.7660444f, 0.7771460f, 0.7880108f, 0.7986355f,
855 0.8090170f, 0.8191520f, 0.8290376f, 0.8386706f, 0.8480481f, 0.8571673f,
856 0.8660254f, 0.8746197f, 0.8829476f, 0.8910065f, 0.8987940f, 0.9063078f,
857 0.9135455f, 0.9205049f, 0.9271839f, 0.9335804f, 0.9396926f, 0.9455186f,
858 0.9510565f, 0.9563048f, 0.9612617f, 0.9659258f, 0.9702957f, 0.9743701f,
859 0.9781476f, 0.9816272f, 0.9848078f, 0.9876883f, 0.9902681f, 0.9925462f,
860 0.9945219f, 0.9961947f, 0.9975641f, 0.9986295f, 0.9993908f, 0.9998477f,
861 1.0000000f, 0.9998477f, 0.9993908f, 0.9986295f, 0.9975641f, 0.9961947f,
862 0.9945219f, 0.9925462f, 0.9902681f, 0.9876883f, 0.9848078f, 0.9816272f,
863 0.9781476f, 0.9743701f, 0.9702957f, 0.9659258f, 0.9612617f, 0.9563048f,
864 0.9510565f, 0.9455186f, 0.9396926f, 0.9335804f, 0.9271839f, 0.9205049f,
865 0.9135455f, 0.9063078f, 0.8987940f, 0.8910065f, 0.8829476f, 0.8746197f,
866 0.8660254f, 0.8571673f, 0.8480481f, 0.8386706f, 0.8290376f, 0.8191520f,
867 0.8090170f, 0.7986355f, 0.7880108f, 0.7771460f, 0.7660444f, 0.7547096f,
868 0.7431448f, 0.7313537f, 0.7193398f, 0.7071068f, 0.6946584f, 0.6819984f,
869 0.6691306f, 0.6560590f, 0.6427876f, 0.6293204f, 0.6156615f, 0.6018150f,
870 0.5877853f, 0.5735764f, 0.5591929f, 0.5446390f, 0.5299193f, 0.5150381f,
871 0.5000000f, 0.4848096f, 0.4694716f, 0.4539905f, 0.4383711f, 0.4226183f,
872 0.4067366f, 0.3907311f, 0.3746066f, 0.3583679f, 0.3420201f, 0.3255682f,
873 0.3090170f, 0.2923717f, 0.2756374f, 0.2588190f, 0.2419219f, 0.2249511f,
874 0.2079117f, 0.1908090f, 0.1736482f, 0.1564345f, 0.1391731f, 0.1218693f,
875 0.1045285f, 0.0871557f, 0.0697565f, 0.0523360f, 0.0348995f, 0.0174524f,
876 0.0000000f, -0.0174524f, -0.0348995f, -0.0523360f, -0.0697565f, -0.0871557f,
877 -0.1045285f, -0.1218693f, -0.1391731f, -0.1564345f, -0.1736482f, -0.1908090f,
878 -0.2079117f, -0.2249511f, -0.2419219f, -0.2588190f, -0.2756374f, -0.2923717f,
879 -0.3090170f, -0.3255682f, -0.3420201f, -0.3583679f, -0.3746066f, -0.3907311f,
880 -0.4067366f, -0.4226183f, -0.4383711f, -0.4539905f, -0.4694716f, -0.4848096f,
881 -0.5000000f, -0.5150381f, -0.5299193f, -0.5446390f, -0.5591929f, -0.5735764f,
882 -0.5877853f, -0.6018150f, -0.6156615f, -0.6293204f, -0.6427876f, -0.6560590f,
883 -0.6691306f, -0.6819984f, -0.6946584f, -0.7071068f, -0.7193398f, -0.7313537f,
884 -0.7431448f, -0.7547096f, -0.7660444f, -0.7771460f, -0.7880108f, -0.7986355f,
885 -0.8090170f, -0.8191520f, -0.8290376f, -0.8386706f, -0.8480481f, -0.8571673f,
886 -0.8660254f, -0.8746197f, -0.8829476f, -0.8910065f, -0.8987940f, -0.9063078f,
887 -0.9135455f, -0.9205049f, -0.9271839f, -0.9335804f, -0.9396926f, -0.9455186f,
888 -0.9510565f, -0.9563048f, -0.9612617f, -0.9659258f, -0.9702957f, -0.9743701f,
889 -0.9781476f, -0.9816272f, -0.9848078f, -0.9876883f, -0.9902681f, -0.9925462f,
890 -0.9945219f, -0.9961947f, -0.9975641f, -0.9986295f, -0.9993908f, -0.9998477f,
891 -1.0000000f, -0.9998477f, -0.9993908f, -0.9986295f, -0.9975641f, -0.9961947f,
892 -0.9945219f, -0.9925462f, -0.9902681f, -0.9876883f, -0.9848078f, -0.9816272f,
893 -0.9781476f, -0.9743701f, -0.9702957f, -0.9659258f, -0.9612617f, -0.9563048f,
894 -0.9510565f, -0.9455186f, -0.9396926f, -0.9335804f, -0.9271839f, -0.9205049f,
895 -0.9135455f, -0.9063078f, -0.8987940f, -0.8910065f, -0.8829476f, -0.8746197f,
896 -0.8660254f, -0.8571673f, -0.8480481f, -0.8386706f, -0.8290376f, -0.8191520f,
897 -0.8090170f, -0.7986355f, -0.7880108f, -0.7771460f, -0.7660444f, -0.7547096f,
898 -0.7431448f, -0.7313537f, -0.7193398f, -0.7071068f, -0.6946584f, -0.6819984f,
899 -0.6691306f, -0.6560590f, -0.6427876f, -0.6293204f, -0.6156615f, -0.6018150f,
900 -0.5877853f, -0.5735764f, -0.5591929f, -0.5446390f, -0.5299193f, -0.5150381f,
901 -0.5000000f, -0.4848096f, -0.4694716f, -0.4539905f, -0.4383711f, -0.4226183f,
902 -0.4067366f, -0.3907311f, -0.3746066f, -0.3583679f, -0.3420201f, -0.3255682f,
903 -0.3090170f, -0.2923717f, -0.2756374f, -0.2588190f, -0.2419219f, -0.2249511f,
904 -0.2079117f, -0.1908090f, -0.1736482f, -0.1564345f, -0.1391731f, -0.1218693f,
905 -0.1045285f, -0.0871557f, -0.0697565f, -0.0523360f, -0.0348995f, -0.0174524f,
906 -0.0000000f, 0.0174524f, 0.0348995f, 0.0523360f, 0.0697565f, 0.0871557f,
907 0.1045285f, 0.1218693f, 0.1391731f, 0.1564345f, 0.1736482f, 0.1908090f,
908 0.2079117f, 0.2249511f, 0.2419219f, 0.2588190f, 0.2756374f, 0.2923717f,
909 0.3090170f, 0.3255682f, 0.3420201f, 0.3583679f, 0.3746066f, 0.3907311f,
910 0.4067366f, 0.4226183f, 0.4383711f, 0.4539905f, 0.4694716f, 0.4848096f,
911 0.5000000f, 0.5150381f, 0.5299193f, 0.5446390f, 0.5591929f, 0.5735764f,
912 0.5877853f, 0.6018150f, 0.6156615f, 0.6293204f, 0.6427876f, 0.6560590f,
913 0.6691306f, 0.6819984f, 0.6946584f, 0.7071068f, 0.7193398f, 0.7313537f,
914 0.7431448f, 0.7547096f, 0.7660444f, 0.7771460f, 0.7880108f, 0.7986355f,
915 0.8090170f, 0.8191520f, 0.8290376f, 0.8386706f, 0.8480481f, 0.8571673f,
916 0.8660254f, 0.8746197f, 0.8829476f, 0.8910065f, 0.8987940f, 0.9063078f,
917 0.9135455f, 0.9205049f, 0.9271839f, 0.9335804f, 0.9396926f, 0.9455186f,
918 0.9510565f, 0.9563048f, 0.9612617f, 0.9659258f, 0.9702957f, 0.9743701f,
919 0.9781476f, 0.9816272f, 0.9848078f, 0.9876883f, 0.9902681f, 0.9925462f,
920 0.9945219f, 0.9961947f, 0.9975641f, 0.9986295f, 0.9993908f, 0.9998477f,
926 sincos( int angle, float& cosval, float& sinval )
928 angle += (angle < 0 ? 360 : 0);
929 sinval = SinTable[angle];
930 cosval = SinTable[450 - angle];
934 constructs polygon that represents elliptic arc.
936 void ellipse2Poly( Point center, Size axes, int angle,
937 int arcStart, int arcEnd,
938 int delta, CV_OUT std::vector<Point>& pts )
940 std::vector<Point2d> _pts;
941 ellipse2Poly(Point2d(center.x, center.y), Size2d(axes.width, axes.height), angle,
942 arcStart, arcEnd, delta, _pts);
943 Point prevPt(INT_MIN, INT_MIN);
945 for (unsigned int i = 0; i < _pts.size(); ++i)
948 pt.x = cvRound(_pts[i].x);
949 pt.y = cvRound(_pts[i].y);
956 // If there are no points, it's a zero-size polygon
957 if (pts.size() == 1) {
958 pts.assign(2, center);
962 void ellipse2Poly( Point2d center, Size2d axes, int angle,
963 int arc_start, int arc_end,
964 int delta, std::vector<Point2d>& pts )
966 CV_INSTRUMENT_REGION()
976 if( arc_start > arc_end )
982 while( arc_start < 0 )
987 while( arc_end > 360 )
992 if( arc_end - arc_start > 360 )
997 sincos( angle, alpha, beta );
1000 for( i = arc_start; i < arc_end + delta; i += delta )
1004 if( angle > arc_end )
1009 x = axes.width * SinTable[450-angle];
1010 y = axes.height * SinTable[angle];
1012 pt.x = center.x + x * alpha - y * beta;
1013 pt.y = center.y + x * beta + y * alpha;
1017 // If there are no points, it's a zero-size polygon
1018 if( pts.size() == 1) {
1019 pts.assign(2,center);
1025 EllipseEx( Mat& img, Point2l center, Size2l axes,
1026 int angle, int arc_start, int arc_end,
1027 const void* color, int thickness, int line_type )
1029 axes.width = std::abs(axes.width), axes.height = std::abs(axes.height);
1030 int delta = (int)((std::max(axes.width,axes.height)+(XY_ONE>>1))>>XY_SHIFT);
1031 delta = delta < 3 ? 90 : delta < 10 ? 30 : delta < 15 ? 18 : 5;
1033 std::vector<Point2d> _v;
1034 ellipse2Poly( Point2d((double)center.x, (double)center.y), Size2d((double)axes.width, (double)axes.height), angle, arc_start, arc_end, delta, _v );
1036 std::vector<Point2l> v;
1037 Point2l prevPt(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF);
1039 for (unsigned int i = 0; i < _v.size(); ++i)
1042 pt.x = (int64)cvRound(_v[i].x / XY_ONE) << XY_SHIFT;
1043 pt.y = (int64)cvRound(_v[i].y / XY_ONE) << XY_SHIFT;
1044 pt.x += cvRound(_v[i].x - pt.x);
1045 pt.y += cvRound(_v[i].y - pt.y);
1052 // If there are no points, it's a zero-size polygon
1053 if (v.size() == 1) {
1054 v.assign(2, center);
1057 if( thickness >= 0 )
1058 PolyLine( img, &v[0], (int)v.size(), false, color, thickness, line_type, XY_SHIFT );
1059 else if( arc_end - arc_start >= 360 )
1060 FillConvexPoly( img, &v[0], (int)v.size(), color, line_type, XY_SHIFT );
1063 v.push_back(center);
1064 std::vector<PolyEdge> edges;
1065 CollectPolyEdges( img, &v[0], (int)v.size(), edges, color, line_type, XY_SHIFT );
1066 FillEdgeCollection( img, edges, color );
1071 /****************************************************************************************\
1072 * Polygons filling *
1073 \****************************************************************************************/
1075 static inline void ICV_HLINE_X(uchar* ptr, int xl, int xr, const uchar* color, int pix_size)
1077 uchar* hline_min_ptr = (uchar*)(ptr) + (xl)*(pix_size);
1078 uchar* hline_end_ptr = (uchar*)(ptr) + (xr+1)*(pix_size);
1079 uchar* hline_ptr = hline_min_ptr;
1081 memset(hline_min_ptr, *color, hline_end_ptr-hline_min_ptr);
1082 else//if (pix_size != 1)
1084 if (hline_min_ptr < hline_end_ptr)
1086 memcpy(hline_ptr, color, pix_size);
1087 hline_ptr += pix_size;
1088 }//end if (hline_min_ptr < hline_end_ptr)
1089 size_t sizeToCopy = pix_size;
1090 while(hline_ptr < hline_end_ptr)
1092 memcpy(hline_ptr, hline_min_ptr, sizeToCopy);
1093 hline_ptr += sizeToCopy;
1094 sizeToCopy = std::min(2*sizeToCopy, static_cast<size_t>(hline_end_ptr-hline_ptr));
1095 }//end while(hline_ptr < hline_end_ptr)
1096 }//end if (pix_size != 1)
1100 static inline void ICV_HLINE(uchar* ptr, int xl, int xr, const void* color, int pix_size)
1102 ICV_HLINE_X(ptr, xl, xr, reinterpret_cast<const uchar*>(color), pix_size);
1106 /* filling convex polygon. v - array of vertices, ntps - number of points */
1108 FillConvexPoly( Mat& img, const Point2l* v, int npts, const void* color, int line_type, int shift )
1118 int delta = 1 << shift >> 1;
1121 int64 xmin, xmax, ymin, ymax;
1122 uchar* ptr = img.ptr();
1123 Size size = img.size();
1124 int pix_size = (int)img.elemSize();
1128 if( line_type < CV_AA )
1129 delta1 = delta2 = XY_ONE >> 1;
1131 delta1 = XY_ONE - 1, delta2 = 0;
1134 p0.x <<= XY_SHIFT - shift;
1135 p0.y <<= XY_SHIFT - shift;
1137 assert( 0 <= shift && shift <= XY_SHIFT );
1138 xmin = xmax = v[0].x;
1139 ymin = ymax = v[0].y;
1141 for( i = 0; i < npts; i++ )
1150 ymax = std::max( ymax, p.y );
1151 xmax = std::max( xmax, p.x );
1152 xmin = MIN( xmin, p.x );
1154 p.x <<= XY_SHIFT - shift;
1155 p.y <<= XY_SHIFT - shift;
1157 if( line_type <= 8 )
1162 pt0.x = (int)(p0.x >> XY_SHIFT);
1163 pt0.y = (int)(p0.y >> XY_SHIFT);
1164 pt1.x = (int)(p.x >> XY_SHIFT);
1165 pt1.y = (int)(p.y >> XY_SHIFT);
1166 Line( img, pt0, pt1, color, line_type );
1169 Line2( img, p0, p, color );
1172 LineAA( img, p0, p, color );
1176 xmin = (xmin + delta) >> shift;
1177 xmax = (xmax + delta) >> shift;
1178 ymin = (ymin + delta) >> shift;
1179 ymax = (ymax + delta) >> shift;
1181 if( npts < 3 || (int)xmax < 0 || (int)ymax < 0 || (int)xmin >= size.width || (int)ymin >= size.height )
1184 ymax = MIN( ymax, size.height - 1 );
1185 edge[0].idx = edge[1].idx = imin;
1187 edge[0].ye = edge[1].ye = y = (int)ymin;
1189 edge[1].di = npts - 1;
1191 edge[0].x = edge[1].x = -XY_ONE;
1192 edge[0].dx = edge[1].dx = 0;
1198 if( line_type < CV_AA || y < (int)ymax || y == (int)ymin )
1200 for( i = 0; i < 2; i++ )
1202 if( y >= edge[i].ye )
1204 int idx0 = edge[i].idx, di = edge[i].di;
1205 int idx = idx0 + di;
1206 if (idx >= npts) idx -= npts;
1209 for (; edges-- > 0; )
1211 ty = (int)((v[idx].y + delta) >> shift);
1214 int64 xs = v[idx0].x;
1215 int64 xe = v[idx].x;
1216 if (shift != XY_SHIFT)
1218 xs <<= XY_SHIFT - shift;
1219 xe <<= XY_SHIFT - shift;
1223 edge[i].dx = ((xe - xs)*2 + (ty - y)) / (2 * (ty - y));
1230 if (idx >= npts) idx -= npts;
1241 int left = 0, right = 1;
1242 if (edge[0].x > edge[1].x)
1244 left = 1, right = 0;
1247 int xx1 = (int)((edge[left].x + delta1) >> XY_SHIFT);
1248 int xx2 = (int)((edge[right].x + delta2) >> XY_SHIFT);
1250 if( xx2 >= 0 && xx1 < size.width )
1254 if( xx2 >= size.width )
1255 xx2 = size.width - 1;
1256 ICV_HLINE( ptr, xx1, xx2, color, pix_size );
1261 // TODO optimize scan for negative y
1264 edge[0].x += edge[0].dx;
1265 edge[1].x += edge[1].dx;
1268 while( ++y <= (int)ymax );
1272 /******** Arbitrary polygon **********/
1275 CollectPolyEdges( Mat& img, const Point2l* v, int count, std::vector<PolyEdge>& edges,
1276 const void* color, int line_type, int shift, Point offset )
1278 int i, delta = offset.y + ((1 << shift) >> 1);
1279 Point2l pt0 = v[count-1], pt1;
1280 pt0.x = (pt0.x + offset.x) << (XY_SHIFT - shift);
1281 pt0.y = (pt0.y + delta) >> shift;
1283 edges.reserve( edges.size() + count );
1285 for( i = 0; i < count; i++, pt0 = pt1 )
1291 pt1.x = (pt1.x + offset.x) << (XY_SHIFT - shift);
1292 pt1.y = (pt1.y + delta) >> shift;
1294 if( line_type < CV_AA )
1296 t0.y = pt0.y; t1.y = pt1.y;
1297 t0.x = (pt0.x + (XY_ONE >> 1)) >> XY_SHIFT;
1298 t1.x = (pt1.x + (XY_ONE >> 1)) >> XY_SHIFT;
1299 Line( img, t0, t1, color, line_type );
1303 t0.x = pt0.x; t1.x = pt1.x;
1304 t0.y = pt0.y << XY_SHIFT;
1305 t1.y = pt1.y << XY_SHIFT;
1306 LineAA( img, t0, t1, color );
1309 if( pt0.y == pt1.y )
1314 edge.y0 = (int)(pt0.y);
1315 edge.y1 = (int)(pt1.y);
1320 edge.y0 = (int)(pt1.y);
1321 edge.y1 = (int)(pt0.y);
1324 edge.dx = (pt1.x - pt0.x) / (pt1.y - pt0.y);
1325 edges.push_back(edge);
1331 bool operator ()(const PolyEdge& e1, const PolyEdge& e2)
1333 return e1.y0 - e2.y0 ? e1.y0 < e2.y0 :
1334 e1.x - e2.x ? e1.x < e2.x : e1.dx < e2.dx;
1338 /**************** helper macros and functions for sequence/contour processing ***********/
1341 FillEdgeCollection( Mat& img, std::vector<PolyEdge>& edges, const void* color )
1344 int i, y, total = (int)edges.size();
1345 Size size = img.size();
1347 int y_max = INT_MIN, y_min = INT_MAX;
1348 int64 x_max = 0xFFFFFFFFFFFFFFFF, x_min = 0x7FFFFFFFFFFFFFFF;
1349 int pix_size = (int)img.elemSize();
1354 for( i = 0; i < total; i++ )
1356 PolyEdge& e1 = edges[i];
1357 assert( e1.y0 < e1.y1 );
1358 // Determine x-coordinate of the end of the edge.
1359 // (This is not necessary x-coordinate of any vertex in the array.)
1360 int64 x1 = e1.x + (e1.y1 - e1.y0) * e1.dx;
1361 y_min = std::min( y_min, e1.y0 );
1362 y_max = std::max( y_max, e1.y1 );
1363 x_min = std::min( x_min, e1.x );
1364 x_max = std::max( x_max, e1.x );
1365 x_min = std::min( x_min, x1 );
1366 x_max = std::max( x_max, x1 );
1369 if( y_max < 0 || y_min >= size.height || x_max < 0 || x_min >= ((int64)size.width<<XY_SHIFT) )
1372 std::sort( edges.begin(), edges.end(), CmpEdges() );
1376 edges.push_back(tmp); // after this point we do not add
1377 // any elements to edges, thus we can use pointers
1381 y_max = MIN( y_max, size.height );
1383 for( y = e->y0; y < y_max; y++ )
1385 PolyEdge *last, *prelast, *keep_prelast;
1388 int clipline = y < 0;
1392 while( last || e->y0 == y )
1394 if( last && last->y1 == y )
1396 // exclude edge if y reaches its lower point
1397 prelast->next = last->next;
1401 keep_prelast = prelast;
1402 if( last && (e->y0 > y || last->x < e->x) )
1404 // go to the next edge in active list
1408 else if( i < total )
1410 // insert new edge into active list if y reaches its upper point
1423 // convert x's from fixed-point to image coordinates
1424 uchar *timg = img.ptr(y);
1427 if (keep_prelast->x > prelast->x)
1429 x1 = (int)((prelast->x + XY_ONE - 1) >> XY_SHIFT);
1430 x2 = (int)(keep_prelast->x >> XY_SHIFT);
1434 x1 = (int)((keep_prelast->x + XY_ONE - 1) >> XY_SHIFT);
1435 x2 = (int)(prelast->x >> XY_SHIFT);
1438 // clip and draw the line
1439 if( x1 < size.width && x2 >= 0 )
1443 if( x2 >= size.width )
1444 x2 = size.width - 1;
1445 ICV_HLINE( timg, x1, x2, color, pix_size );
1448 keep_prelast->x += keep_prelast->dx;
1449 prelast->x += prelast->dx;
1454 // sort edges (using bubble sort)
1462 while( last != keep_prelast && last->next != 0 )
1464 PolyEdge *te = last->next;
1467 if( last->x > te->x )
1470 last->next = te->next;
1481 keep_prelast = prelast;
1483 while( sort_flag && keep_prelast != tmp.next && keep_prelast != &tmp );
1488 /* draws simple or filled circle */
1490 Circle( Mat& img, Point center, int radius, const void* color, int fill )
1492 Size size = img.size();
1493 size_t step = img.step;
1494 int pix_size = (int)img.elemSize();
1495 uchar* ptr = img.ptr();
1496 int err = 0, dx = radius, dy = 0, plus = 1, minus = (radius << 1) - 1;
1497 int inside = center.x >= radius && center.x < size.width - radius &&
1498 center.y >= radius && center.y < size.height - radius;
1500 #define ICV_PUT_POINT( ptr, x ) \
1501 memcpy( ptr + (x)*pix_size, color, pix_size );
1506 int y11 = center.y - dy, y12 = center.y + dy, y21 = center.y - dx, y22 = center.y + dx;
1507 int x11 = center.x - dx, x12 = center.x + dx, x21 = center.x - dy, x22 = center.x + dy;
1511 uchar *tptr0 = ptr + y11 * step;
1512 uchar *tptr1 = ptr + y12 * step;
1516 ICV_PUT_POINT( tptr0, x11 );
1517 ICV_PUT_POINT( tptr1, x11 );
1518 ICV_PUT_POINT( tptr0, x12 );
1519 ICV_PUT_POINT( tptr1, x12 );
1523 ICV_HLINE( tptr0, x11, x12, color, pix_size );
1524 ICV_HLINE( tptr1, x11, x12, color, pix_size );
1527 tptr0 = ptr + y21 * step;
1528 tptr1 = ptr + y22 * step;
1532 ICV_PUT_POINT( tptr0, x21 );
1533 ICV_PUT_POINT( tptr1, x21 );
1534 ICV_PUT_POINT( tptr0, x22 );
1535 ICV_PUT_POINT( tptr1, x22 );
1539 ICV_HLINE( tptr0, x21, x22, color, pix_size );
1540 ICV_HLINE( tptr1, x21, x22, color, pix_size );
1543 else if( x11 < size.width && x12 >= 0 && y21 < size.height && y22 >= 0 )
1547 x11 = std::max( x11, 0 );
1548 x12 = MIN( x12, size.width - 1 );
1551 if( (unsigned)y11 < (unsigned)size.height )
1553 uchar *tptr = ptr + y11 * step;
1558 ICV_PUT_POINT( tptr, x11 );
1559 if( x12 < size.width )
1560 ICV_PUT_POINT( tptr, x12 );
1563 ICV_HLINE( tptr, x11, x12, color, pix_size );
1566 if( (unsigned)y12 < (unsigned)size.height )
1568 uchar *tptr = ptr + y12 * step;
1573 ICV_PUT_POINT( tptr, x11 );
1574 if( x12 < size.width )
1575 ICV_PUT_POINT( tptr, x12 );
1578 ICV_HLINE( tptr, x11, x12, color, pix_size );
1581 if( x21 < size.width && x22 >= 0 )
1585 x21 = std::max( x21, 0 );
1586 x22 = MIN( x22, size.width - 1 );
1589 if( (unsigned)y21 < (unsigned)size.height )
1591 uchar *tptr = ptr + y21 * step;
1596 ICV_PUT_POINT( tptr, x21 );
1597 if( x22 < size.width )
1598 ICV_PUT_POINT( tptr, x22 );
1601 ICV_HLINE( tptr, x21, x22, color, pix_size );
1604 if( (unsigned)y22 < (unsigned)size.height )
1606 uchar *tptr = ptr + y22 * step;
1611 ICV_PUT_POINT( tptr, x21 );
1612 if( x22 < size.width )
1613 ICV_PUT_POINT( tptr, x22 );
1616 ICV_HLINE( tptr, x21, x22, color, pix_size );
1624 mask = (err <= 0) - 1;
1626 err -= minus & mask;
1631 #undef ICV_PUT_POINT
1636 ThickLine( Mat& img, Point2l p0, Point2l p1, const void* color,
1637 int thickness, int line_type, int flags, int shift )
1639 static const double INV_XY_ONE = 1./XY_ONE;
1641 p0.x <<= XY_SHIFT - shift;
1642 p0.y <<= XY_SHIFT - shift;
1643 p1.x <<= XY_SHIFT - shift;
1644 p1.y <<= XY_SHIFT - shift;
1646 if( thickness <= 1 )
1648 if( line_type < CV_AA )
1650 if( line_type == 1 || line_type == 4 || shift == 0 )
1652 p0.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT;
1653 p0.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT;
1654 p1.x = (p1.x + (XY_ONE>>1)) >> XY_SHIFT;
1655 p1.y = (p1.y + (XY_ONE>>1)) >> XY_SHIFT;
1656 Line( img, p0, p1, color, line_type );
1659 Line2( img, p0, p1, color );
1662 LineAA( img, p0, p1, color );
1666 Point2l pt[4], dp = Point2l(0,0);
1667 double dx = (p0.x - p1.x)*INV_XY_ONE, dy = (p1.y - p0.y)*INV_XY_ONE;
1668 double r = dx * dx + dy * dy;
1669 int i, oddThickness = thickness & 1;
1670 thickness <<= XY_SHIFT - 1;
1672 if( fabs(r) > DBL_EPSILON )
1674 r = (thickness + oddThickness*XY_ONE*0.5)/std::sqrt(r);
1675 dp.x = cvRound( dy * r );
1676 dp.y = cvRound( dx * r );
1678 pt[0].x = p0.x + dp.x;
1679 pt[0].y = p0.y + dp.y;
1680 pt[1].x = p0.x - dp.x;
1681 pt[1].y = p0.y - dp.y;
1682 pt[2].x = p1.x - dp.x;
1683 pt[2].y = p1.y - dp.y;
1684 pt[3].x = p1.x + dp.x;
1685 pt[3].y = p1.y + dp.y;
1687 FillConvexPoly( img, pt, 4, color, line_type, XY_SHIFT );
1690 for( i = 0; i < 2; i++ )
1694 if( line_type < CV_AA )
1697 center.x = (int)((p0.x + (XY_ONE>>1)) >> XY_SHIFT);
1698 center.y = (int)((p0.y + (XY_ONE>>1)) >> XY_SHIFT);
1699 Circle( img, center, (thickness + (XY_ONE>>1)) >> XY_SHIFT, color, 1 );
1703 EllipseEx( img, p0, Size2l(thickness, thickness),
1704 0, 0, 360, color, -1, line_type );
1714 PolyLine( Mat& img, const Point2l* v, int count, bool is_closed,
1715 const void* color, int thickness,
1716 int line_type, int shift )
1718 if( !v || count <= 0 )
1721 int i = is_closed ? count - 1 : 0;
1722 int flags = 2 + !is_closed;
1724 CV_Assert( 0 <= shift && shift <= XY_SHIFT && thickness >= 0 );
1727 for( i = !is_closed; i < count; i++ )
1730 ThickLine( img, p0, p, color, thickness, line_type, flags, shift );
1736 /* ----------------------------------------------------------------------------------------- */
1737 /* ADDING A SET OF PREDEFINED MARKERS WHICH COULD BE USED TO HIGHLIGHT POSITIONS IN AN IMAGE */
1738 /* ----------------------------------------------------------------------------------------- */
1740 void drawMarker(InputOutputArray img, Point position, const Scalar& color, int markerType, int markerSize, int thickness, int line_type)
1744 // The cross marker case
1746 line(img, Point(position.x-(markerSize/2), position.y), Point(position.x+(markerSize/2), position.y), color, thickness, line_type);
1747 line(img, Point(position.x, position.y-(markerSize/2)), Point(position.x, position.y+(markerSize/2)), color, thickness, line_type);
1750 // The tilted cross marker case
1751 case MARKER_TILTED_CROSS:
1752 line(img, Point(position.x-(markerSize/2), position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
1753 line(img, Point(position.x+(markerSize/2), position.y-(markerSize/2)), Point(position.x-(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
1756 // The star marker case
1758 line(img, Point(position.x-(markerSize/2), position.y), Point(position.x+(markerSize/2), position.y), color, thickness, line_type);
1759 line(img, Point(position.x, position.y-(markerSize/2)), Point(position.x, position.y+(markerSize/2)), color, thickness, line_type);
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);
1764 // The diamond marker case
1765 case MARKER_DIAMOND:
1766 line(img, Point(position.x, position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y), color, thickness, line_type);
1767 line(img, Point(position.x+(markerSize/2), position.y), Point(position.x, position.y+(markerSize/2)), color, thickness, line_type);
1768 line(img, Point(position.x, position.y+(markerSize/2)), Point(position.x-(markerSize/2), position.y), color, thickness, line_type);
1769 line(img, Point(position.x-(markerSize/2), position.y), Point(position.x, position.y-(markerSize/2)), color, thickness, line_type);
1772 // The square marker case
1774 line(img, Point(position.x-(markerSize/2), position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y-(markerSize/2)), color, thickness, line_type);
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-(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
1777 line(img, Point(position.x-(markerSize/2), position.y+(markerSize/2)), Point(position.x-(markerSize/2), position.y-(markerSize/2)), color, thickness, line_type);
1780 // The triangle up marker case
1781 case MARKER_TRIANGLE_UP:
1782 line(img, Point(position.x-(markerSize/2), position.y+(markerSize/2)), Point(position.x+(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
1783 line(img, Point(position.x+(markerSize/2), position.y+(markerSize/2)), Point(position.x, position.y-(markerSize/2)), color, thickness, line_type);
1784 line(img, Point(position.x, position.y-(markerSize/2)), Point(position.x-(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
1787 // The triangle down marker case
1788 case MARKER_TRIANGLE_DOWN:
1789 line(img, Point(position.x-(markerSize/2), position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y-(markerSize/2)), color, thickness, line_type);
1790 line(img, Point(position.x+(markerSize/2), position.y-(markerSize/2)), Point(position.x, position.y+(markerSize/2)), color, thickness, line_type);
1791 line(img, Point(position.x, position.y+(markerSize/2)), Point(position.x-(markerSize/2), position.y-(markerSize/2)), color, thickness, line_type);
1794 // If any number that doesn't exist is entered as marker type, draw a cross marker, to avoid crashes
1796 drawMarker(img, position, color, MARKER_CROSS, markerSize, thickness, line_type);
1801 /****************************************************************************************\
1802 * External functions *
1803 \****************************************************************************************/
1805 void line( InputOutputArray _img, Point pt1, Point pt2, const Scalar& color,
1806 int thickness, int line_type, int shift )
1808 CV_INSTRUMENT_REGION()
1810 Mat img = _img.getMat();
1812 if( line_type == CV_AA && img.depth() != CV_8U )
1815 CV_Assert( 0 < thickness && thickness <= MAX_THICKNESS );
1816 CV_Assert( 0 <= shift && shift <= XY_SHIFT );
1819 scalarToRawData( color, buf, img.type(), 0 );
1820 ThickLine( img, pt1, pt2, buf, thickness, line_type, 3, shift );
1823 void arrowedLine(InputOutputArray img, Point pt1, Point pt2, const Scalar& color,
1824 int thickness, int line_type, int shift, double tipLength)
1826 CV_INSTRUMENT_REGION()
1828 const double tipSize = norm(pt1-pt2)*tipLength; // Factor to normalize the size of the tip depending on the length of the arrow
1830 line(img, pt1, pt2, color, thickness, line_type, shift);
1832 const double angle = atan2( (double) pt1.y - pt2.y, (double) pt1.x - pt2.x );
1834 Point p(cvRound(pt2.x + tipSize * cos(angle + CV_PI / 4)),
1835 cvRound(pt2.y + tipSize * sin(angle + CV_PI / 4)));
1836 line(img, p, pt2, color, thickness, line_type, shift);
1838 p.x = cvRound(pt2.x + tipSize * cos(angle - CV_PI / 4));
1839 p.y = cvRound(pt2.y + tipSize * sin(angle - CV_PI / 4));
1840 line(img, p, pt2, color, thickness, line_type, shift);
1843 void rectangle( InputOutputArray _img, Point pt1, Point pt2,
1844 const Scalar& color, int thickness,
1845 int lineType, int shift )
1847 CV_INSTRUMENT_REGION()
1849 Mat img = _img.getMat();
1851 if( lineType == CV_AA && img.depth() != CV_8U )
1854 CV_Assert( thickness <= MAX_THICKNESS );
1855 CV_Assert( 0 <= shift && shift <= XY_SHIFT );
1858 scalarToRawData(color, buf, img.type(), 0);
1869 if( thickness >= 0 )
1870 PolyLine( img, pt, 4, true, buf, thickness, lineType, shift );
1872 FillConvexPoly( img, pt, 4, buf, lineType, shift );
1876 void rectangle( InputOutputArray img, Rect rec,
1877 const Scalar& color, int thickness,
1878 int lineType, int shift )
1880 CV_INSTRUMENT_REGION()
1882 if( rec.area() > 0 )
1883 rectangle( img, rec.tl(), rec.br() - Point(1<<shift,1<<shift),
1884 color, thickness, lineType, shift );
1888 void circle( InputOutputArray _img, Point center, int radius,
1889 const Scalar& color, int thickness, int line_type, int shift )
1891 CV_INSTRUMENT_REGION()
1893 Mat img = _img.getMat();
1895 if( line_type == CV_AA && img.depth() != CV_8U )
1898 CV_Assert( radius >= 0 && thickness <= MAX_THICKNESS &&
1899 0 <= shift && shift <= XY_SHIFT );
1902 scalarToRawData(color, buf, img.type(), 0);
1904 if( thickness > 1 || line_type != LINE_8 || shift > 0 )
1906 Point2l _center(center);
1907 int64 _radius(radius);
1908 _center.x <<= XY_SHIFT - shift;
1909 _center.y <<= XY_SHIFT - shift;
1910 _radius <<= XY_SHIFT - shift;
1911 EllipseEx( img, _center, Size2l(_radius, _radius),
1912 0, 0, 360, buf, thickness, line_type );
1915 Circle( img, center, radius, buf, thickness < 0 );
1919 void ellipse( InputOutputArray _img, Point center, Size axes,
1920 double angle, double start_angle, double end_angle,
1921 const Scalar& color, int thickness, int line_type, int shift )
1923 CV_INSTRUMENT_REGION()
1925 Mat img = _img.getMat();
1927 if( line_type == CV_AA && img.depth() != CV_8U )
1930 CV_Assert( axes.width >= 0 && axes.height >= 0 &&
1931 thickness <= MAX_THICKNESS && 0 <= shift && shift <= XY_SHIFT );
1934 scalarToRawData(color, buf, img.type(), 0);
1936 int _angle = cvRound(angle);
1937 int _start_angle = cvRound(start_angle);
1938 int _end_angle = cvRound(end_angle);
1939 Point2l _center(center);
1941 _center.x <<= XY_SHIFT - shift;
1942 _center.y <<= XY_SHIFT - shift;
1943 _axes.width <<= XY_SHIFT - shift;
1944 _axes.height <<= XY_SHIFT - shift;
1946 EllipseEx( img, _center, _axes, _angle, _start_angle,
1947 _end_angle, buf, thickness, line_type );
1950 void ellipse(InputOutputArray _img, const RotatedRect& box, const Scalar& color,
1951 int thickness, int lineType)
1953 CV_INSTRUMENT_REGION()
1955 Mat img = _img.getMat();
1957 if( lineType == CV_AA && img.depth() != CV_8U )
1960 CV_Assert( box.size.width >= 0 && box.size.height >= 0 &&
1961 thickness <= MAX_THICKNESS );
1964 scalarToRawData(color, buf, img.type(), 0);
1966 int _angle = cvRound(box.angle);
1967 Point2l center(cvRound(box.center.x),
1968 cvRound(box.center.y));
1969 center.x = (center.x << XY_SHIFT) + cvRound((box.center.x - center.x)*XY_ONE);
1970 center.y = (center.y << XY_SHIFT) + cvRound((box.center.y - center.y)*XY_ONE);
1971 Size2l axes(cvRound(box.size.width),
1972 cvRound(box.size.height));
1973 axes.width = (axes.width << (XY_SHIFT - 1)) + cvRound((box.size.width - axes.width)*(XY_ONE>>1));
1974 axes.height = (axes.height << (XY_SHIFT - 1)) + cvRound((box.size.height - axes.height)*(XY_ONE>>1));
1975 EllipseEx( img, center, axes, _angle, 0, 360, buf, thickness, lineType );
1978 void fillConvexPoly( Mat& img, const Point* pts, int npts,
1979 const Scalar& color, int line_type, int shift )
1981 CV_INSTRUMENT_REGION()
1983 if( !pts || npts <= 0 )
1986 if( line_type == CV_AA && img.depth() != CV_8U )
1990 CV_Assert( 0 <= shift && shift <= XY_SHIFT );
1991 scalarToRawData(color, buf, img.type(), 0);
1992 std::vector<Point2l> _pts(pts, pts + npts);
1993 FillConvexPoly( img, _pts.data(), npts, buf, line_type, shift );
1997 void fillPoly( Mat& img, const Point** pts, const int* npts, int ncontours,
1998 const Scalar& color, int line_type,
1999 int shift, Point offset )
2001 CV_INSTRUMENT_REGION()
2003 if( line_type == CV_AA && img.depth() != CV_8U )
2006 CV_Assert( pts && npts && ncontours >= 0 && 0 <= shift && shift <= XY_SHIFT );
2009 scalarToRawData(color, buf, img.type(), 0);
2011 std::vector<PolyEdge> edges;
2014 for( i = 0; i < ncontours; i++ )
2017 edges.reserve( total + 1 );
2018 for (i = 0; i < ncontours; i++)
2020 std::vector<Point2l> _pts(pts[i], pts[i] + npts[i]);
2021 CollectPolyEdges(img, _pts.data(), npts[i], edges, buf, line_type, shift, offset);
2024 FillEdgeCollection(img, edges, buf);
2028 void polylines( Mat& img, const Point* const* pts, const int* npts, int ncontours, bool isClosed,
2029 const Scalar& color, int thickness, int line_type, int shift )
2031 CV_INSTRUMENT_REGION()
2033 if( line_type == CV_AA && img.depth() != CV_8U )
2036 CV_Assert( pts && npts && ncontours >= 0 &&
2037 0 <= thickness && thickness <= MAX_THICKNESS &&
2038 0 <= shift && shift <= XY_SHIFT );
2041 scalarToRawData( color, buf, img.type(), 0 );
2043 for( int i = 0; i < ncontours; i++ )
2045 std::vector<Point2l> _pts(pts[i], pts[i]+npts[i]);
2046 PolyLine( img, _pts.data(), npts[i], isClosed, buf, thickness, line_type, shift );
2051 enum { FONT_SIZE_SHIFT=8, FONT_ITALIC_ALPHA=(1 << 8),
2052 FONT_ITALIC_DIGIT=(2 << 8), FONT_ITALIC_PUNCT=(4 << 8),
2053 FONT_ITALIC_BRACES=(8 << 8), FONT_HAVE_GREEK=(16 << 8),
2054 FONT_HAVE_CYRILLIC=(32 << 8) };
2056 static const int HersheyPlain[] = {
2057 (5 + 4*16) + 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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
2061 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 193, 84,
2062 194, 85, 86, 87, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
2063 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
2064 195, 223, 196, 88 };
2066 static const int HersheyPlainItalic[] = {
2067 (5 + 4*16) + FONT_ITALIC_ALPHA + FONT_HAVE_GREEK,
2068 199, 214, 217, 233, 219, 197, 234, 216, 221, 222, 228, 225, 211, 224, 210, 220,
2069 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 212, 213, 191, 226, 192,
2070 215, 190, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
2071 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 193, 84,
2072 194, 85, 86, 87, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
2073 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
2074 195, 223, 196, 88 };
2076 static const int HersheyComplexSmall[] = {
2077 (6 + 7*16) + 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, 2213, 1241, 1238, 1242,
2080 1215, 1273, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013,
2081 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1223, 1084,
2082 1224, 1247, 586, 1249, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
2083 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126,
2084 1225, 1229, 1226, 1246 };
2086 static const int HersheyComplexSmallItalic[] = {
2087 (6 + 7*16) + FONT_ITALIC_ALPHA + FONT_HAVE_GREEK,
2088 1199, 1214, 1217, 1275, 1274, 1271, 1272, 1216, 1221, 1222, 1219, 1232, 1211, 1231, 1210, 1220,
2089 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1212, 1213, 1241, 1238, 1242,
2090 1215, 1273, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063,
2091 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1223, 1084,
2092 1224, 1247, 586, 1249, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161,
2093 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176,
2094 1225, 1229, 1226, 1246 };
2096 static const int HersheySimplex[] = {
2097 (9 + 12*16) + FONT_HAVE_GREEK,
2098 2199, 714, 717, 733, 719, 697, 734, 716, 721, 722, 728, 725, 711, 724, 710, 720,
2099 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 712, 713, 691, 726, 692,
2100 715, 690, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513,
2101 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 693, 584,
2102 694, 2247, 586, 2249, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611,
2103 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626,
2104 695, 723, 696, 2246 };
2106 static const int HersheyDuplex[] = {
2107 (9 + 12*16) + FONT_HAVE_GREEK,
2108 2199, 2714, 2728, 2732, 2719, 2733, 2718, 2727, 2721, 2722, 2723, 2725, 2711, 2724, 2710, 2720,
2109 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2712, 2713, 2730, 2726, 2731,
2110 2715, 2734, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513,
2111 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2223, 2084,
2112 2224, 2247, 587, 2249, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611,
2113 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626,
2114 2225, 2229, 2226, 2246 };
2116 static const int HersheyComplex[] = {
2117 (9 + 12*16) + FONT_HAVE_GREEK + FONT_HAVE_CYRILLIC,
2118 2199, 2214, 2217, 2275, 2274, 2271, 2272, 2216, 2221, 2222, 2219, 2232, 2211, 2231, 2210, 2220,
2119 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2212, 2213, 2241, 2238, 2242,
2120 2215, 2273, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013,
2121 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2223, 2084,
2122 2224, 2247, 587, 2249, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111,
2123 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126,
2124 2225, 2229, 2226, 2246, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811,
2125 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826,
2126 2827, 2828, 2829, 2830, 2831, 2832, 2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909,
2127 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924,
2128 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932};
2130 static const int HersheyComplexItalic[] = {
2131 (9 + 12*16) + FONT_ITALIC_ALPHA + FONT_ITALIC_DIGIT + FONT_ITALIC_PUNCT +
2132 FONT_HAVE_GREEK + FONT_HAVE_CYRILLIC,
2133 2199, 2764, 2778, 2782, 2769, 2783, 2768, 2777, 2771, 2772, 2219, 2232, 2211, 2231, 2210, 2220,
2134 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2212, 2213, 2241, 2238, 2242,
2135 2765, 2273, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063,
2136 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2223, 2084,
2137 2224, 2247, 587, 2249, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161,
2138 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176,
2139 2225, 2229, 2226, 2246 };
2141 static const int HersheyTriplex[] = {
2142 (9 + 12*16) + FONT_HAVE_GREEK,
2143 2199, 3214, 3228, 3232, 3219, 3233, 3218, 3227, 3221, 3222, 3223, 3225, 3211, 3224, 3210, 3220,
2144 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3212, 3213, 3230, 3226, 3231,
2145 3215, 3234, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013,
2146 2014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 2223, 2084,
2147 2224, 2247, 587, 2249, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111,
2148 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126,
2149 2225, 2229, 2226, 2246 };
2151 static const int HersheyTriplexItalic[] = {
2152 (9 + 12*16) + FONT_ITALIC_ALPHA + FONT_ITALIC_DIGIT +
2153 FONT_ITALIC_PUNCT + FONT_HAVE_GREEK,
2154 2199, 3264, 3278, 3282, 3269, 3233, 3268, 3277, 3271, 3272, 3223, 3225, 3261, 3224, 3260, 3270,
2155 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3262, 3263, 3230, 3226, 3231,
2156 3265, 3234, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063,
2157 2064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 2223, 2084,
2158 2224, 2247, 587, 2249, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161,
2159 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176,
2160 2225, 2229, 2226, 2246 };
2162 static const int HersheyScriptSimplex[] = {
2163 (9 + 12*16) + FONT_ITALIC_ALPHA + FONT_HAVE_GREEK,
2164 2199, 714, 717, 733, 719, 697, 734, 716, 721, 722, 728, 725, 711, 724, 710, 720,
2165 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 712, 713, 691, 726, 692,
2166 715, 690, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563,
2167 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 693, 584,
2168 694, 2247, 586, 2249, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661,
2169 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676,
2170 695, 723, 696, 2246 };
2172 static const int HersheyScriptComplex[] = {
2173 (9 + 12*16) + FONT_ITALIC_ALPHA + FONT_ITALIC_DIGIT + FONT_ITALIC_PUNCT + FONT_HAVE_GREEK,
2174 2199, 2764, 2778, 2782, 2769, 2783, 2768, 2777, 2771, 2772, 2219, 2232, 2211, 2231, 2210, 2220,
2175 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2212, 2213, 2241, 2238, 2242,
2176 2215, 2273, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562, 2563,
2177 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2223, 2084,
2178 2224, 2247, 586, 2249, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661,
2179 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676,
2180 2225, 2229, 2226, 2246 };
2183 static const int* getFontData(int fontFace)
2185 bool isItalic = (fontFace & FONT_ITALIC) != 0;
2186 const int* ascii = 0;
2188 switch( fontFace & 15 )
2190 case FONT_HERSHEY_SIMPLEX:
2191 ascii = HersheySimplex;
2193 case FONT_HERSHEY_PLAIN:
2194 ascii = !isItalic ? HersheyPlain : HersheyPlainItalic;
2196 case FONT_HERSHEY_DUPLEX:
2197 ascii = HersheyDuplex;
2199 case FONT_HERSHEY_COMPLEX:
2200 ascii = !isItalic ? HersheyComplex : HersheyComplexItalic;
2202 case FONT_HERSHEY_TRIPLEX:
2203 ascii = !isItalic ? HersheyTriplex : HersheyTriplexItalic;
2205 case FONT_HERSHEY_COMPLEX_SMALL:
2206 ascii = !isItalic ? HersheyComplexSmall : HersheyComplexSmallItalic;
2208 case FONT_HERSHEY_SCRIPT_SIMPLEX:
2209 ascii = HersheyScriptSimplex;
2211 case FONT_HERSHEY_SCRIPT_COMPLEX:
2212 ascii = HersheyScriptComplex;
2215 CV_Error( CV_StsOutOfRange, "Unknown font type" );
2220 inline void readCheck(int &c, int &i, const String &text, int fontFace)
2223 int leftBoundary = ' ', rightBoundary = 127;
2225 if(c >= 0x80 && fontFace == FONT_HERSHEY_COMPLEX)
2227 if(c == 0xD0 && (uchar)text[i + 1] >= 0x90 && (uchar)text[i + 1] <= 0xBF)
2229 c = (uchar)text[++i] - 17;
2231 rightBoundary = 175;
2233 else if(c == 0xD1 && (uchar)text[i + 1] >= 0x80 && (uchar)text[i + 1] <= 0x8F)
2235 c = (uchar)text[++i] + 47;
2237 rightBoundary = 191;
2241 if(c >= 0xC0 && text[i+1] != 0) //2 bytes utf
2244 if(c >= 0xE0 && text[i+1] != 0) //3 bytes utf
2247 if(c >= 0xF0 && text[i+1] != 0) //4 bytes utf
2250 if(c >= 0xF8 && text[i+1] != 0) //5 bytes utf
2253 if(c >= 0xFC && text[i+1] != 0) //6 bytes utf
2260 if(c >= rightBoundary || c < leftBoundary)
2264 extern const char* g_HersheyGlyphs[];
2266 void putText( InputOutputArray _img, const String& text, Point org,
2267 int fontFace, double fontScale, Scalar color,
2268 int thickness, int line_type, bool bottomLeftOrigin )
2271 CV_INSTRUMENT_REGION()
2277 Mat img = _img.getMat();
2278 const int* ascii = getFontData(fontFace);
2281 scalarToRawData(color, buf, img.type(), 0);
2283 int base_line = -(ascii[0] & 15);
2284 int hscale = cvRound(fontScale*XY_ONE), vscale = hscale;
2286 if( line_type == CV_AA && img.depth() != CV_8U )
2289 if( bottomLeftOrigin )
2292 int64 view_x = (int64)org.x << XY_SHIFT;
2293 int64 view_y = ((int64)org.y << XY_SHIFT) + base_line*vscale;
2294 std::vector<Point2l> pts;
2295 pts.reserve(1 << 10);
2296 const char **faces = cv::g_HersheyGlyphs;
2298 for( int i = 0; i < (int)text.size(); i++ )
2300 int c = (uchar)text[i];
2303 readCheck(c, i, text, fontFace);
2305 const char* ptr = faces[ascii[(c-' ')+1]];
2306 p.x = (uchar)ptr[0] - 'R';
2307 p.y = (uchar)ptr[1] - 'R';
2308 int64 dx = p.y*hscale;
2309 view_x -= p.x*hscale;
2314 if( *ptr == ' ' || !*ptr )
2316 if( pts.size() > 1 )
2317 PolyLine( img, &pts[0], (int)pts.size(), false, buf, thickness, line_type, XY_SHIFT );
2324 p.x = (uchar)ptr[0] - 'R';
2325 p.y = (uchar)ptr[1] - 'R';
2327 pts.push_back(Point2l(p.x*hscale + view_x, p.y*vscale + view_y));
2334 Size getTextSize( const String& text, int fontFace, double fontScale, int thickness, int* _base_line)
2338 const char **faces = cv::g_HersheyGlyphs;
2339 const int* ascii = getFontData(fontFace);
2341 int base_line = (ascii[0] & 15);
2342 int cap_line = (ascii[0] >> 4) & 15;
2343 size.height = cvRound((cap_line + base_line)*fontScale + (thickness+1)/2);
2345 for( int i = 0; i < (int)text.size(); i++ )
2347 int c = (uchar)text[i];
2350 readCheck(c, i, text, fontFace);
2352 const char* ptr = faces[ascii[(c-' ')+1]];
2353 p.x = (uchar)ptr[0] - 'R';
2354 p.y = (uchar)ptr[1] - 'R';
2355 view_x += (p.y - p.x)*fontScale;
2358 size.width = cvRound(view_x + thickness);
2360 *_base_line = cvRound(base_line*fontScale + thickness*0.5);
2364 double getFontScaleFromHeight(const int fontFace, const int pixelHeight, const int thickness)
2366 // By https://stackoverflow.com/a/27898487/1531708
2367 const int* ascii = getFontData(fontFace);
2369 int base_line = (ascii[0] & 15);
2370 int cap_line = (ascii[0] >> 4) & 15;
2372 return static_cast<double>(pixelHeight - static_cast<double>((thickness + 1)) / 2.0) / static_cast<double>(cap_line + base_line);
2378 void cv::fillConvexPoly(InputOutputArray _img, InputArray _points,
2379 const Scalar& color, int lineType, int shift)
2381 CV_INSTRUMENT_REGION()
2383 Mat img = _img.getMat(), points = _points.getMat();
2384 CV_Assert(points.checkVector(2, CV_32S) >= 0);
2385 fillConvexPoly(img, points.ptr<Point>(), points.rows*points.cols*points.channels()/2, color, lineType, shift);
2389 void cv::fillPoly(InputOutputArray _img, InputArrayOfArrays pts,
2390 const Scalar& color, int lineType, int shift, Point offset)
2392 CV_INSTRUMENT_REGION()
2394 Mat img = _img.getMat();
2395 int i, ncontours = (int)pts.total();
2396 if( ncontours == 0 )
2398 AutoBuffer<Point*> _ptsptr(ncontours);
2399 AutoBuffer<int> _npts(ncontours);
2400 Point** ptsptr = _ptsptr.data();
2401 int* npts = _npts.data();
2403 for( i = 0; i < ncontours; i++ )
2405 Mat p = pts.getMat(i);
2406 CV_Assert(p.checkVector(2, CV_32S) >= 0);
2407 ptsptr[i] = p.ptr<Point>();
2408 npts[i] = p.rows*p.cols*p.channels()/2;
2410 fillPoly(img, (const Point**)ptsptr, npts, (int)ncontours, color, lineType, shift, offset);
2414 void cv::polylines(InputOutputArray _img, InputArrayOfArrays pts,
2415 bool isClosed, const Scalar& color,
2416 int thickness, int lineType, int shift )
2418 CV_INSTRUMENT_REGION()
2420 Mat img = _img.getMat();
2421 bool manyContours = pts.kind() == _InputArray::STD_VECTOR_VECTOR ||
2422 pts.kind() == _InputArray::STD_VECTOR_MAT;
2423 int i, ncontours = manyContours ? (int)pts.total() : 1;
2424 if( ncontours == 0 )
2426 AutoBuffer<Point*> _ptsptr(ncontours);
2427 AutoBuffer<int> _npts(ncontours);
2428 Point** ptsptr = _ptsptr.data();
2429 int* npts = _npts.data();
2431 for( i = 0; i < ncontours; i++ )
2433 Mat p = pts.getMat(manyContours ? i : -1);
2434 if( p.total() == 0 )
2440 CV_Assert(p.checkVector(2, CV_32S) >= 0);
2441 ptsptr[i] = p.ptr<Point>();
2442 npts[i] = p.rows*p.cols*p.channels()/2;
2444 polylines(img, (const Point**)ptsptr, npts, (int)ncontours, isClosed, color, thickness, lineType, shift);
2451 static void addChildContour(InputArrayOfArrays contours,
2453 const Vec4i* hierarchy,
2454 int i, std::vector<CvSeq>& seq,
2455 std::vector<CvSeqBlock>& block)
2457 for( ; i >= 0; i = hierarchy[i][0] )
2459 Mat ci = contours.getMat(i);
2460 cvMakeSeqHeaderForArray(CV_SEQ_POLYGON, sizeof(CvSeq), sizeof(Point),
2461 !ci.empty() ? (void*)ci.ptr() : 0, (int)ci.total(),
2462 &seq[i], &block[i] );
2464 int h_next = hierarchy[i][0], h_prev = hierarchy[i][1],
2465 v_next = hierarchy[i][2], v_prev = hierarchy[i][3];
2466 seq[i].h_next = (0 <= h_next && h_next < (int)ncontours) ? &seq[h_next] : 0;
2467 seq[i].h_prev = (0 <= h_prev && h_prev < (int)ncontours) ? &seq[h_prev] : 0;
2468 seq[i].v_next = (0 <= v_next && v_next < (int)ncontours) ? &seq[v_next] : 0;
2469 seq[i].v_prev = (0 <= v_prev && v_prev < (int)ncontours) ? &seq[v_prev] : 0;
2472 addChildContour(contours, ncontours, hierarchy, v_next, seq, block);
2477 void cv::drawContours( InputOutputArray _image, InputArrayOfArrays _contours,
2478 int contourIdx, const Scalar& color, int thickness,
2479 int lineType, InputArray _hierarchy,
2480 int maxLevel, Point offset )
2482 CV_INSTRUMENT_REGION()
2484 Mat image = _image.getMat(), hierarchy = _hierarchy.getMat();
2485 CvMat _cimage = image;
2487 size_t ncontours = _contours.total();
2488 size_t i = 0, first = 0, last = ncontours;
2489 std::vector<CvSeq> seq;
2490 std::vector<CvSeqBlock> block;
2498 for( i = first; i < last; i++ )
2501 if( contourIdx >= 0 )
2503 CV_Assert( 0 <= contourIdx && contourIdx < (int)last );
2505 last = contourIdx + 1;
2508 for( i = first; i < last; i++ )
2510 Mat ci = _contours.getMat((int)i);
2513 int npoints = ci.checkVector(2, CV_32S);
2514 CV_Assert( npoints > 0 );
2515 cvMakeSeqHeaderForArray( CV_SEQ_POLYGON, sizeof(CvSeq), sizeof(Point),
2516 ci.ptr(), npoints, &seq[i], &block[i] );
2519 if( hierarchy.empty() || maxLevel == 0 )
2520 for( i = first; i < last; i++ )
2522 seq[i].h_next = i < last-1 ? &seq[i+1] : 0;
2523 seq[i].h_prev = i > first ? &seq[i-1] : 0;
2527 size_t count = last - first;
2528 CV_Assert(hierarchy.total() == ncontours && hierarchy.type() == CV_32SC4 );
2529 const Vec4i* h = hierarchy.ptr<Vec4i>();
2531 if( count == ncontours )
2533 for( i = first; i < last; i++ )
2535 int h_next = h[i][0], h_prev = h[i][1],
2536 v_next = h[i][2], v_prev = h[i][3];
2537 seq[i].h_next = (size_t)h_next < count ? &seq[h_next] : 0;
2538 seq[i].h_prev = (size_t)h_prev < count ? &seq[h_prev] : 0;
2539 seq[i].v_next = (size_t)v_next < count ? &seq[v_next] : 0;
2540 seq[i].v_prev = (size_t)v_prev < count ? &seq[v_prev] : 0;
2545 int child = h[first][2];
2548 addChildContour(_contours, ncontours, h, child, seq, block);
2549 seq[first].v_next = &seq[child];
2554 cvDrawContours( &_cimage, &seq[first], color, color, contourIdx >= 0 ?
2555 -maxLevel : maxLevel, thickness, lineType, offset );
2560 static const int CodeDeltas[8][2] =
2561 { {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1} };
2563 #define CV_ADJUST_EDGE_COUNT( count, seq ) \
2564 ((count) -= ((count) == (seq)->total && !CV_IS_SEQ_CLOSED(seq)))
2566 #if defined __GNUC__ && __GNUC__ >= 8
2567 #pragma GCC diagnostic push
2568 #pragma GCC diagnostic ignored "-Wclass-memaccess"
2572 cvDrawContours( void* _img, CvSeq* contour,
2573 CvScalar _externalColor, CvScalar _holeColor,
2574 int maxLevel, int thickness,
2575 int line_type, CvPoint _offset )
2577 CvSeq *contour0 = contour, *h_next = 0;
2578 CvTreeNodeIterator iterator;
2579 std::vector<cv::PolyEdge> edges;
2580 std::vector<cv::Point2l> pts;
2581 cv::Scalar externalColor = _externalColor, holeColor = _holeColor;
2582 cv::Mat img = cv::cvarrToMat(_img);
2583 cv::Point offset = _offset;
2584 double ext_buf[4], hole_buf[4];
2586 if( line_type == CV_AA && img.depth() != CV_8U )
2592 CV_Assert( thickness <= MAX_THICKNESS );
2594 scalarToRawData( externalColor, ext_buf, img.type(), 0 );
2595 scalarToRawData( holeColor, hole_buf, img.type(), 0 );
2597 maxLevel = MAX(maxLevel, INT_MIN+2);
2598 maxLevel = MIN(maxLevel, INT_MAX-1);
2602 h_next = contour->h_next;
2603 contour->h_next = 0;
2604 maxLevel = -maxLevel+1;
2607 cvInitTreeNodeIterator( &iterator, contour, maxLevel );
2608 while( (contour = (CvSeq*)cvNextTreeNode( &iterator )) != 0 )
2611 int i, count = contour->total;
2612 int elem_type = CV_MAT_TYPE(contour->flags);
2613 void* clr = (contour->flags & CV_SEQ_FLAG_HOLE) == 0 ? ext_buf : hole_buf;
2615 cvStartReadSeq( contour, &reader, 0 );
2616 CV_Assert(reader.ptr != NULL);
2620 if( CV_IS_SEQ_CHAIN_CONTOUR( contour ))
2622 cv::Point pt = ((CvChain*)contour)->origin;
2623 cv::Point prev_pt = pt;
2624 char prev_code = reader.ptr ? reader.ptr[0] : '\0';
2628 for( i = 0; i < count; i++ )
2631 CV_READ_SEQ_ELEM( code, reader );
2633 assert( (code & ~7) == 0 );
2635 if( code != prev_code )
2638 if( thickness >= 0 )
2639 cv::ThickLine( img, prev_pt, pt, clr, thickness, line_type, 2, 0 );
2645 pt.x += CodeDeltas[(int)code][0];
2646 pt.y += CodeDeltas[(int)code][1];
2649 if( thickness >= 0 )
2650 cv::ThickLine( img, prev_pt,
2651 cv::Point(((CvChain*)contour)->origin) + offset,
2652 clr, thickness, line_type, 2, 0 );
2654 cv::CollectPolyEdges(img, &pts[0], (int)pts.size(),
2655 edges, ext_buf, line_type, 0, offset);
2657 else if( CV_IS_SEQ_POLYLINE( contour ))
2659 CV_Assert( elem_type == CV_32SC2 );
2663 count -= !CV_IS_SEQ_CLOSED(contour);
2664 CV_READ_SEQ_ELEM( pt1, reader );
2669 for( i = 0; i < count; i++ )
2671 CV_READ_SEQ_ELEM( pt2, reader );
2673 if( thickness >= 0 )
2674 cv::ThickLine( img, pt1, pt2, clr, thickness, line_type, 2, shift );
2680 cv::CollectPolyEdges( img, &pts[0], (int)pts.size(),
2681 edges, ext_buf, line_type, 0, cv::Point() );
2686 cv::FillEdgeCollection( img, edges, ext_buf );
2688 if( h_next && contour0 )
2689 contour0->h_next = h_next;
2693 cvClipLine( CvSize size, CvPoint* pt1, CvPoint* pt2 )
2695 CV_Assert( pt1 && pt2 );
2696 return cv::clipLine( size, *(cv::Point*)pt1, *(cv::Point*)pt2 );
2701 cvEllipse2Poly( CvPoint center, CvSize axes, int angle,
2702 int arc_start, int arc_end, CvPoint* _pts, int delta )
2704 std::vector<cv::Point> pts;
2705 cv::ellipse2Poly( Point(center), Size(axes), angle, arc_start, arc_end, delta, pts );
2706 memcpy( _pts, &pts[0], pts.size()*sizeof(_pts[0]) );
2707 return (int)pts.size();
2711 cvColorToScalar( double packed_color, int type )
2715 if( CV_MAT_DEPTH( type ) == CV_8U )
2717 int icolor = cvRound( packed_color );
2718 if( CV_MAT_CN( type ) > 1 )
2720 scalar.val[0] = icolor & 255;
2721 scalar.val[1] = (icolor >> 8) & 255;
2722 scalar.val[2] = (icolor >> 16) & 255;
2723 scalar.val[3] = (icolor >> 24) & 255;
2727 scalar.val[0] = cv::saturate_cast<uchar>( icolor );
2728 scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
2731 else if( CV_MAT_DEPTH( type ) == CV_8S )
2733 int icolor = cvRound( packed_color );
2734 if( CV_MAT_CN( type ) > 1 )
2736 scalar.val[0] = (char)icolor;
2737 scalar.val[1] = (char)(icolor >> 8);
2738 scalar.val[2] = (char)(icolor >> 16);
2739 scalar.val[3] = (char)(icolor >> 24);
2743 scalar.val[0] = cv::saturate_cast<schar>( icolor );
2744 scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
2749 int cn = CV_MAT_CN( type );
2753 scalar.val[0] = packed_color;
2754 scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
2757 scalar.val[0] = scalar.val[1] = packed_color;
2758 scalar.val[2] = scalar.val[3] = 0;
2761 scalar.val[0] = scalar.val[1] = scalar.val[2] = packed_color;
2765 scalar.val[0] = scalar.val[1] =
2766 scalar.val[2] = scalar.val[3] = packed_color;
2775 cvInitLineIterator( const CvArr* img, CvPoint pt1, CvPoint pt2,
2776 CvLineIterator* iterator, int connectivity,
2779 CV_Assert( iterator != 0 );
2780 cv::LineIterator li(cv::cvarrToMat(img), pt1, pt2, connectivity, left_to_right!=0);
2782 iterator->err = li.err;
2783 iterator->minus_delta = li.minusDelta;
2784 iterator->plus_delta = li.plusDelta;
2785 iterator->minus_step = li.minusStep;
2786 iterator->plus_step = li.plusStep;
2787 iterator->ptr = li.ptr;
2793 cvLine( CvArr* _img, CvPoint pt1, CvPoint pt2, CvScalar color,
2794 int thickness, int line_type, int shift )
2796 cv::Mat img = cv::cvarrToMat(_img);
2797 cv::line( img, pt1, pt2, color, thickness, line_type, shift );
2801 cvRectangle( CvArr* _img, CvPoint pt1, CvPoint pt2,
2802 CvScalar color, int thickness,
2803 int line_type, int shift )
2805 cv::Mat img = cv::cvarrToMat(_img);
2806 cv::rectangle( img, pt1, pt2, color, thickness, line_type, shift );
2810 cvRectangleR( CvArr* _img, CvRect rec,
2811 CvScalar color, int thickness,
2812 int line_type, int shift )
2814 cv::Mat img = cv::cvarrToMat(_img);
2815 cv::rectangle( img, rec, color, thickness, line_type, shift );
2819 cvCircle( CvArr* _img, CvPoint center, int radius,
2820 CvScalar color, int thickness, int line_type, int shift )
2822 cv::Mat img = cv::cvarrToMat(_img);
2823 cv::circle( img, center, radius, color, thickness, line_type, shift );
2827 cvEllipse( CvArr* _img, CvPoint center, CvSize axes,
2828 double angle, double start_angle, double end_angle,
2829 CvScalar color, int thickness, int line_type, int shift )
2831 cv::Mat img = cv::cvarrToMat(_img);
2832 cv::ellipse( img, center, axes, angle, start_angle, end_angle,
2833 color, thickness, line_type, shift );
2837 cvFillConvexPoly( CvArr* _img, const CvPoint *pts, int npts,
2838 CvScalar color, int line_type, int shift )
2840 cv::Mat img = cv::cvarrToMat(_img);
2841 cv::fillConvexPoly( img, (const cv::Point*)pts, npts,
2842 color, line_type, shift );
2846 cvFillPoly( CvArr* _img, CvPoint **pts, const int *npts, int ncontours,
2847 CvScalar color, int line_type, int shift )
2849 cv::Mat img = cv::cvarrToMat(_img);
2851 cv::fillPoly( img, (const cv::Point**)pts, npts, ncontours, color, line_type, shift );
2855 cvPolyLine( CvArr* _img, CvPoint **pts, const int *npts,
2856 int ncontours, int closed, CvScalar color,
2857 int thickness, int line_type, int shift )
2859 cv::Mat img = cv::cvarrToMat(_img);
2861 cv::polylines( img, (const cv::Point**)pts, npts, ncontours,
2862 closed != 0, color, thickness, line_type, shift );
2866 cvPutText( CvArr* _img, const char *text, CvPoint org, const CvFont *_font, CvScalar color )
2868 cv::Mat img = cv::cvarrToMat(_img);
2869 CV_Assert( text != 0 && _font != 0);
2870 cv::putText( img, text, org, _font->font_face, (_font->hscale+_font->vscale)*0.5,
2871 color, _font->thickness, _font->line_type,
2872 CV_IS_IMAGE(_img) && ((IplImage*)_img)->origin != 0 );
2877 cvInitFont( CvFont *font, int font_face, double hscale, double vscale,
2878 double shear, int thickness, int line_type )
2880 CV_Assert( font != 0 && hscale > 0 && vscale > 0 && thickness >= 0 );
2882 font->ascii = cv::getFontData(font_face);
2883 font->font_face = font_face;
2884 font->hscale = (float)hscale;
2885 font->vscale = (float)vscale;
2886 font->thickness = thickness;
2887 font->shear = (float)shear;
2888 font->greek = font->cyrillic = 0;
2889 font->line_type = line_type;
2893 cvGetTextSize( const char *text, const CvFont *_font, CvSize *_size, int *_base_line )
2895 CV_Assert(text != 0 && _font != 0);
2896 cv::Size size = cv::getTextSize( text, _font->font_face, (_font->hscale + _font->vscale)*0.5,
2897 _font->thickness, _base_line );
2902 #if defined __GNUC__ && __GNUC__ >= 8
2903 #pragma GCC diagnostic pop // "-Wclass-memaccess"