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.
44 #define XY_ONE (1 << XY_SHIFT)
46 #define CV_DRAWING_STORAGE_BLOCK ((1 << 12) - 256)
48 typedef struct CvPolyEdge
53 struct CvPolyEdge *next;
61 icvCollectPolyEdges( CvMat* img, CvSeq* v, CvContour* edges,
62 const void* color, int line_type,
63 int shift, CvPoint offset=cvPoint(0,0) );
66 icvFillEdgeCollection( CvMat* img, CvContour* edges, const void* color );
69 icvPolyLine( CvMat* img, CvPoint *v, int count, int closed,
70 const void* color, int thickness, int line_type, int shift );
73 icvFillConvexPoly( CvMat* img, CvPoint* v, int npts,
74 const void* color, int line_type, int shift );
76 /****************************************************************************************\
78 \****************************************************************************************/
81 cvClipLine( CvSize img_size, CvPoint* pt1, CvPoint* pt2 )
85 CV_FUNCNAME( "cvClipLine" );
91 int right = img_size.width-1, bottom = img_size.height-1;
94 CV_ERROR( CV_StsNullPtr, "One of point pointers is NULL" );
96 if( right < 0 || bottom < 0 )
97 CV_ERROR( CV_StsOutOfRange, "Image width or height are negative" );
99 x1 = pt1->x; y1 = pt1->y; x2 = pt2->x; y2 = pt2->y;
100 c1 = (x1 < 0) + (x1 > right) * 2 + (y1 < 0) * 4 + (y1 > bottom) * 8;
101 c2 = (x2 < 0) + (x2 > right) * 2 + (y2 < 0) * 4 + (y2 > bottom) * 8;
103 if( (c1 & c2) == 0 && (c1 | c2) != 0 )
109 a = c1 < 8 ? 0 : bottom;
110 x1 += (int) (((int64) (a - y1)) * (x2 - x1) / (y2 - y1));
112 c1 = (x1 < 0) + (x1 > right) * 2;
116 a = c2 < 8 ? 0 : bottom;
117 x2 += (int) (((int64) (a - y2)) * (x2 - x1) / (y2 - y1));
119 c2 = (x2 < 0) + (x2 > right) * 2;
121 if( (c1 & c2) == 0 && (c1 | c2) != 0 )
125 a = c1 == 1 ? 0 : right;
126 y1 += (int) (((int64) (a - x1)) * (y2 - y1) / (x2 - x1));
132 a = c2 == 1 ? 0 : right;
133 y2 += (int) (((int64) (a - x2)) * (y2 - y1) / (x2 - x1));
139 assert( (c1 & c2) != 0 || (x1 | y1 | x2 | y2) >= 0 );
147 result = ( c1 | c2 ) == 0;
156 Initializes line iterator.
157 Returns number of points on the line or negative number if error.
160 cvInitLineIterator( const CvArr* img, CvPoint pt1, CvPoint pt2,
161 CvLineIterator* iterator, int connectivity,
166 CV_FUNCNAME( "cvInitLineIterator" );
170 CvMat stub, *mat = (CvMat*)img;
172 int bt_pix, bt_pix0, step;
174 if( !CV_IS_MAT(mat) )
175 CV_CALL( mat = cvGetMat( mat, &stub ));
178 CV_ERROR( CV_StsNullPtr, "Pointer to the iterator state is NULL" );
180 if( connectivity != 8 && connectivity != 4 )
181 CV_ERROR( CV_StsBadArg, "Connectivity must be 8 or 4" );
183 if( (unsigned)pt1.x >= (unsigned)(mat->width) ||
184 (unsigned)pt2.x >= (unsigned)(mat->width) ||
185 (unsigned)pt1.y >= (unsigned)(mat->height) ||
186 (unsigned)pt2.y >= (unsigned)(mat->height) )
187 CV_ERROR( CV_StsBadPoint,
188 "One of the ending points is outside of the image, use cvClipLine" );
190 bt_pix0 = bt_pix = CV_ELEM_SIZE(mat->type);
201 pt1.x ^= (pt1.x ^ pt2.x) & s;
202 pt1.y ^= (pt1.y ^ pt2.y) & s;
207 bt_pix = (bt_pix ^ s) - s;
210 iterator->ptr = (uchar*)(mat->data.ptr + pt1.y * step + pt1.x * bt_pix0);
214 step = (step ^ s) - s;
216 s = dy > dx ? -1 : 0;
218 /* conditional swaps */
227 if( connectivity == 8 )
229 assert( dx >= 0 && dy >= 0 );
231 iterator->err = dx - (dy + dy);
232 iterator->plus_delta = dx + dx;
233 iterator->minus_delta = -(dy + dy);
234 iterator->plus_step = step;
235 iterator->minus_step = bt_pix;
238 else /* connectivity == 4 */
240 assert( dx >= 0 && dy >= 0 );
243 iterator->plus_delta = (dx + dx) + (dy + dy);
244 iterator->minus_delta = -(dy + dy);
245 iterator->plus_step = step - bt_pix;
246 iterator->minus_step = bt_pix;
256 icvLine( CvMat* mat, CvPoint pt1, CvPoint pt2,
257 const void* color, int connectivity = 8 )
259 if( cvClipLine( cvGetMatSize(mat), &pt1, &pt2 ))
261 CvLineIterator iterator;
262 int pix_size = CV_ELEM_SIZE(mat->type);
265 if( connectivity == 0 )
267 if( connectivity == 1 )
270 count = cvInitLineIterator( mat, pt1, pt2, &iterator, connectivity, 1 );
272 for( i = 0; i < count; i++ )
274 CV_MEMCPY_AUTO( iterator.ptr, color, pix_size );
275 CV_NEXT_LINE_POINT( iterator );
281 /* Correction table depent on the slope */
282 static const uchar icvSlopeCorrTable[] = {
283 181, 181, 181, 182, 182, 183, 184, 185, 187, 188, 190, 192, 194, 196, 198, 201,
284 203, 206, 209, 211, 214, 218, 221, 224, 227, 231, 235, 238, 242, 246, 250, 254
287 /* Gaussian for antialiasing filter */
288 static const int icvFilterTable[] = {
289 168, 177, 185, 194, 202, 210, 218, 224, 231, 236, 241, 246, 249, 252, 254, 254,
290 254, 254, 252, 249, 246, 241, 236, 231, 224, 218, 210, 202, 194, 185, 177, 168,
291 158, 149, 140, 131, 122, 114, 105, 97, 89, 82, 75, 68, 62, 56, 50, 45,
292 40, 36, 32, 28, 25, 22, 19, 16, 14, 12, 11, 9, 8, 7, 5, 5
296 icvLineAA( CvMat* img, CvPoint pt1, CvPoint pt2,
300 int ecount, scount = 0;
306 int cb = ((uchar*)color)[0], cg = ((uchar*)color)[1], cr = ((uchar*)color)[2];
308 int nch = CV_MAT_CN( img->type );
309 uchar* ptr = (uchar*)(img->data.ptr);
310 int step = img->step;
311 CvSize size = cvGetMatSize( img );
313 assert( img && (nch == 1 || nch == 3) && CV_MAT_DEPTH(img->type) == CV_8U );
319 ptr += img->step*2 + 2*nch;
321 size.width = ((size.width - 5) << XY_SHIFT) + 1;
322 size.height = ((size.height - 5) << XY_SHIFT) + 1;
324 if( !cvClipLine( size, &pt1, &pt2 ))
347 y_step = (int) (((int64) dy << XY_SHIFT) / (ax | 1));
349 ecount = (pt2.x >> XY_SHIFT) - (pt1.x >> XY_SHIFT);
350 j = -(pt1.x & (XY_ONE - 1));
351 pt1.y += (int) ((((int64) y_step) * j) >> XY_SHIFT) + (XY_ONE >> 1);
352 slope = (y_step >> (XY_SHIFT - 5)) & 0x3f;
353 slope ^= (y_step < 0 ? 0x3f : 0);
355 /* Get 4-bit fractions for end-point adjustments */
356 i = (pt1.x >> (XY_SHIFT - 7)) & 0x78;
357 j = (pt2.x >> (XY_SHIFT - 7)) & 0x78;
370 x_step = (int) (((int64) dx << XY_SHIFT) / (ay | 1));
373 ecount = (pt2.y >> XY_SHIFT) - (pt1.y >> XY_SHIFT);
374 j = -(pt1.y & (XY_ONE - 1));
375 pt1.x += (int) ((((int64) x_step) * j) >> XY_SHIFT) + (XY_ONE >> 1);
376 slope = (x_step >> (XY_SHIFT - 5)) & 0x3f;
377 slope ^= (x_step < 0 ? 0x3f : 0);
379 /* Get 4-bit fractions for end-point adjustments */
380 i = (pt1.y >> (XY_SHIFT - 7)) & 0x78;
381 j = (pt2.y >> (XY_SHIFT - 7)) & 0x78;
384 slope = (slope & 0x20) ? 0x100 : icvSlopeCorrTable[slope];
386 /* Calc end point correction table */
389 int t1 = ((0x78 - i) | 4) * slope;
390 int t2 = (j | 4) * slope;
394 ep_table[1] = ep_table[3] = ((((j - i) & 0x78) | 4) * slope >> 8) & 0x1ff;
395 ep_table[2] = (t1 >> 8) & 0x1ff;
396 ep_table[4] = ((((j - i) + 0x80) | 4) * slope >> 8) & 0x1ff;
397 ep_table[5] = ((t1 + t0) >> 8) & 0x1ff;
398 ep_table[6] = (t2 >> 8) & 0x1ff;
399 ep_table[7] = ((t2 + t0) >> 8) & 0x1ff;
404 #define ICV_PUT_POINT() \
407 _cb += ((cb - _cb)*a + 127)>> 8;\
409 _cg += ((cg - _cg)*a + 127)>> 8;\
411 _cr += ((cr - _cr)*a + 127)>> 8;\
412 tptr[0] = (uchar)_cb; \
413 tptr[1] = (uchar)_cg; \
414 tptr[2] = (uchar)_cr; \
418 ptr += (pt1.x >> XY_SHIFT) * 3;
422 uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step;
424 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
425 (((ecount >= 2) + 1) & (ecount | 2))];
426 int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
428 a = (ep_corr * icvFilterTable[dist + 32] >> 8) & 0xff;
433 a = (ep_corr * icvFilterTable[dist] >> 8) & 0xff;
438 a = (ep_corr * icvFilterTable[63 - dist] >> 8) & 0xff;
450 ptr += (pt1.y >> XY_SHIFT) * step;
454 uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1) * 3;
456 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
457 (((ecount >= 2) + 1) & (ecount | 2))];
458 int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
460 a = (ep_corr * icvFilterTable[dist + 32] >> 8) & 0xff;
465 a = (ep_corr * icvFilterTable[dist] >> 8) & 0xff;
470 a = (ep_corr * icvFilterTable[63 - dist] >> 8) & 0xff;
484 #define ICV_PUT_POINT() \
487 _cb += ((cb - _cb)*a + 127)>> 8;\
488 tptr[0] = (uchar)_cb; \
493 ptr += (pt1.x >> XY_SHIFT);
497 uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step;
499 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
500 (((ecount >= 2) + 1) & (ecount | 2))];
501 int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
503 a = (ep_corr * icvFilterTable[dist + 32] >> 8) & 0xff;
508 a = (ep_corr * icvFilterTable[dist] >> 8) & 0xff;
513 a = (ep_corr * icvFilterTable[63 - dist] >> 8) & 0xff;
525 ptr += (pt1.y >> XY_SHIFT) * step;
529 uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1);
531 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
532 (((ecount >= 2) + 1) & (ecount | 2))];
533 int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
535 a = (ep_corr * icvFilterTable[dist + 32] >> 8) & 0xff;
540 a = (ep_corr * icvFilterTable[dist] >> 8) & 0xff;
545 a = (ep_corr * icvFilterTable[63 - dist] >> 8) & 0xff;
561 icvLine2( CvMat* img, CvPoint pt1, CvPoint pt2, const void* color )
568 int cb = ((uchar*)color)[0];
569 int cg = ((uchar*)color)[1];
570 int cr = ((uchar*)color)[2];
571 int pix_size = CV_ELEM_SIZE( img->type );
572 uchar *ptr = (uchar*)(img->data.ptr), *tptr;
573 int step = img->step;
574 CvSize size = cvGetMatSize( img );
576 //assert( img && (nch == 1 || nch == 3) && CV_MAT_DEPTH(img->type) == CV_8U );
582 ptr += img->step*2 + 2*pix_size;
584 size.width = ((size.width - 5) << XY_SHIFT) + 1;
585 size.height = ((size.height - 5) << XY_SHIFT) + 1;
587 if( !cvClipLine( size, &pt1, &pt2 ))
610 y_step = (int) (((int64) dy << XY_SHIFT) / (ax | 1));
611 ecount = (pt2.x - pt1.x) >> XY_SHIFT;
624 x_step = (int) (((int64) dx << XY_SHIFT) / (ay | 1));
626 ecount = (pt2.y - pt1.y) >> XY_SHIFT;
629 pt1.x += (XY_ONE >> 1);
630 pt1.y += (XY_ONE >> 1);
634 #define ICV_PUT_POINT() \
636 tptr[0] = (uchar)cb; \
637 tptr[1] = (uchar)cg; \
638 tptr[2] = (uchar)cr; \
641 tptr = ptr + ((pt2.x + (XY_ONE >> 1))>> XY_SHIFT)*3 +
642 ((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)*step;
647 ptr += (pt1.x >> XY_SHIFT) * 3;
651 tptr = ptr + (pt1.y >> XY_SHIFT) * step;
660 ptr += (pt1.y >> XY_SHIFT) * step;
664 tptr = ptr + (pt1.x >> XY_SHIFT) * 3;
674 else if( pix_size == 1 )
676 #define ICV_PUT_POINT() \
678 tptr[0] = (uchar)cb; \
681 tptr = ptr + ((pt2.x + (XY_ONE >> 1))>> XY_SHIFT) +
682 ((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)*step;
687 ptr += (pt1.x >> XY_SHIFT);
691 tptr = ptr + (pt1.y >> XY_SHIFT) * step;
700 ptr += (pt1.y >> XY_SHIFT) * step;
704 tptr = ptr + (pt1.x >> XY_SHIFT);
715 #define ICV_PUT_POINT() \
716 for( j = 0; j < pix_size; j++ ) \
717 tptr[j] = ((uchar*)color)[j];
719 tptr = ptr + ((pt2.x + (XY_ONE >> 1))>> XY_SHIFT)*pix_size +
720 ((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)*step;
725 ptr += (pt1.x >> XY_SHIFT) * pix_size;
729 tptr = ptr + (pt1.y >> XY_SHIFT) * step;
738 ptr += (pt1.y >> XY_SHIFT) * step;
742 tptr = ptr + (pt1.x >> XY_SHIFT) * pix_size;
755 /****************************************************************************************\
756 * Antialiazed Elliptic Arcs via Antialiazed Lines *
757 \****************************************************************************************/
759 static const float icvSinTable[] =
760 { 0.0000000f, 0.0174524f, 0.0348995f, 0.0523360f, 0.0697565f, 0.0871557f,
761 0.1045285f, 0.1218693f, 0.1391731f, 0.1564345f, 0.1736482f, 0.1908090f,
762 0.2079117f, 0.2249511f, 0.2419219f, 0.2588190f, 0.2756374f, 0.2923717f,
763 0.3090170f, 0.3255682f, 0.3420201f, 0.3583679f, 0.3746066f, 0.3907311f,
764 0.4067366f, 0.4226183f, 0.4383711f, 0.4539905f, 0.4694716f, 0.4848096f,
765 0.5000000f, 0.5150381f, 0.5299193f, 0.5446390f, 0.5591929f, 0.5735764f,
766 0.5877853f, 0.6018150f, 0.6156615f, 0.6293204f, 0.6427876f, 0.6560590f,
767 0.6691306f, 0.6819984f, 0.6946584f, 0.7071068f, 0.7193398f, 0.7313537f,
768 0.7431448f, 0.7547096f, 0.7660444f, 0.7771460f, 0.7880108f, 0.7986355f,
769 0.8090170f, 0.8191520f, 0.8290376f, 0.8386706f, 0.8480481f, 0.8571673f,
770 0.8660254f, 0.8746197f, 0.8829476f, 0.8910065f, 0.8987940f, 0.9063078f,
771 0.9135455f, 0.9205049f, 0.9271839f, 0.9335804f, 0.9396926f, 0.9455186f,
772 0.9510565f, 0.9563048f, 0.9612617f, 0.9659258f, 0.9702957f, 0.9743701f,
773 0.9781476f, 0.9816272f, 0.9848078f, 0.9876883f, 0.9902681f, 0.9925462f,
774 0.9945219f, 0.9961947f, 0.9975641f, 0.9986295f, 0.9993908f, 0.9998477f,
775 1.0000000f, 0.9998477f, 0.9993908f, 0.9986295f, 0.9975641f, 0.9961947f,
776 0.9945219f, 0.9925462f, 0.9902681f, 0.9876883f, 0.9848078f, 0.9816272f,
777 0.9781476f, 0.9743701f, 0.9702957f, 0.9659258f, 0.9612617f, 0.9563048f,
778 0.9510565f, 0.9455186f, 0.9396926f, 0.9335804f, 0.9271839f, 0.9205049f,
779 0.9135455f, 0.9063078f, 0.8987940f, 0.8910065f, 0.8829476f, 0.8746197f,
780 0.8660254f, 0.8571673f, 0.8480481f, 0.8386706f, 0.8290376f, 0.8191520f,
781 0.8090170f, 0.7986355f, 0.7880108f, 0.7771460f, 0.7660444f, 0.7547096f,
782 0.7431448f, 0.7313537f, 0.7193398f, 0.7071068f, 0.6946584f, 0.6819984f,
783 0.6691306f, 0.6560590f, 0.6427876f, 0.6293204f, 0.6156615f, 0.6018150f,
784 0.5877853f, 0.5735764f, 0.5591929f, 0.5446390f, 0.5299193f, 0.5150381f,
785 0.5000000f, 0.4848096f, 0.4694716f, 0.4539905f, 0.4383711f, 0.4226183f,
786 0.4067366f, 0.3907311f, 0.3746066f, 0.3583679f, 0.3420201f, 0.3255682f,
787 0.3090170f, 0.2923717f, 0.2756374f, 0.2588190f, 0.2419219f, 0.2249511f,
788 0.2079117f, 0.1908090f, 0.1736482f, 0.1564345f, 0.1391731f, 0.1218693f,
789 0.1045285f, 0.0871557f, 0.0697565f, 0.0523360f, 0.0348995f, 0.0174524f,
790 0.0000000f, -0.0174524f, -0.0348995f, -0.0523360f, -0.0697565f, -0.0871557f,
791 -0.1045285f, -0.1218693f, -0.1391731f, -0.1564345f, -0.1736482f, -0.1908090f,
792 -0.2079117f, -0.2249511f, -0.2419219f, -0.2588190f, -0.2756374f, -0.2923717f,
793 -0.3090170f, -0.3255682f, -0.3420201f, -0.3583679f, -0.3746066f, -0.3907311f,
794 -0.4067366f, -0.4226183f, -0.4383711f, -0.4539905f, -0.4694716f, -0.4848096f,
795 -0.5000000f, -0.5150381f, -0.5299193f, -0.5446390f, -0.5591929f, -0.5735764f,
796 -0.5877853f, -0.6018150f, -0.6156615f, -0.6293204f, -0.6427876f, -0.6560590f,
797 -0.6691306f, -0.6819984f, -0.6946584f, -0.7071068f, -0.7193398f, -0.7313537f,
798 -0.7431448f, -0.7547096f, -0.7660444f, -0.7771460f, -0.7880108f, -0.7986355f,
799 -0.8090170f, -0.8191520f, -0.8290376f, -0.8386706f, -0.8480481f, -0.8571673f,
800 -0.8660254f, -0.8746197f, -0.8829476f, -0.8910065f, -0.8987940f, -0.9063078f,
801 -0.9135455f, -0.9205049f, -0.9271839f, -0.9335804f, -0.9396926f, -0.9455186f,
802 -0.9510565f, -0.9563048f, -0.9612617f, -0.9659258f, -0.9702957f, -0.9743701f,
803 -0.9781476f, -0.9816272f, -0.9848078f, -0.9876883f, -0.9902681f, -0.9925462f,
804 -0.9945219f, -0.9961947f, -0.9975641f, -0.9986295f, -0.9993908f, -0.9998477f,
805 -1.0000000f, -0.9998477f, -0.9993908f, -0.9986295f, -0.9975641f, -0.9961947f,
806 -0.9945219f, -0.9925462f, -0.9902681f, -0.9876883f, -0.9848078f, -0.9816272f,
807 -0.9781476f, -0.9743701f, -0.9702957f, -0.9659258f, -0.9612617f, -0.9563048f,
808 -0.9510565f, -0.9455186f, -0.9396926f, -0.9335804f, -0.9271839f, -0.9205049f,
809 -0.9135455f, -0.9063078f, -0.8987940f, -0.8910065f, -0.8829476f, -0.8746197f,
810 -0.8660254f, -0.8571673f, -0.8480481f, -0.8386706f, -0.8290376f, -0.8191520f,
811 -0.8090170f, -0.7986355f, -0.7880108f, -0.7771460f, -0.7660444f, -0.7547096f,
812 -0.7431448f, -0.7313537f, -0.7193398f, -0.7071068f, -0.6946584f, -0.6819984f,
813 -0.6691306f, -0.6560590f, -0.6427876f, -0.6293204f, -0.6156615f, -0.6018150f,
814 -0.5877853f, -0.5735764f, -0.5591929f, -0.5446390f, -0.5299193f, -0.5150381f,
815 -0.5000000f, -0.4848096f, -0.4694716f, -0.4539905f, -0.4383711f, -0.4226183f,
816 -0.4067366f, -0.3907311f, -0.3746066f, -0.3583679f, -0.3420201f, -0.3255682f,
817 -0.3090170f, -0.2923717f, -0.2756374f, -0.2588190f, -0.2419219f, -0.2249511f,
818 -0.2079117f, -0.1908090f, -0.1736482f, -0.1564345f, -0.1391731f, -0.1218693f,
819 -0.1045285f, -0.0871557f, -0.0697565f, -0.0523360f, -0.0348995f, -0.0174524f,
820 -0.0000000f, 0.0174524f, 0.0348995f, 0.0523360f, 0.0697565f, 0.0871557f,
821 0.1045285f, 0.1218693f, 0.1391731f, 0.1564345f, 0.1736482f, 0.1908090f,
822 0.2079117f, 0.2249511f, 0.2419219f, 0.2588190f, 0.2756374f, 0.2923717f,
823 0.3090170f, 0.3255682f, 0.3420201f, 0.3583679f, 0.3746066f, 0.3907311f,
824 0.4067366f, 0.4226183f, 0.4383711f, 0.4539905f, 0.4694716f, 0.4848096f,
825 0.5000000f, 0.5150381f, 0.5299193f, 0.5446390f, 0.5591929f, 0.5735764f,
826 0.5877853f, 0.6018150f, 0.6156615f, 0.6293204f, 0.6427876f, 0.6560590f,
827 0.6691306f, 0.6819984f, 0.6946584f, 0.7071068f, 0.7193398f, 0.7313537f,
828 0.7431448f, 0.7547096f, 0.7660444f, 0.7771460f, 0.7880108f, 0.7986355f,
829 0.8090170f, 0.8191520f, 0.8290376f, 0.8386706f, 0.8480481f, 0.8571673f,
830 0.8660254f, 0.8746197f, 0.8829476f, 0.8910065f, 0.8987940f, 0.9063078f,
831 0.9135455f, 0.9205049f, 0.9271839f, 0.9335804f, 0.9396926f, 0.9455186f,
832 0.9510565f, 0.9563048f, 0.9612617f, 0.9659258f, 0.9702957f, 0.9743701f,
833 0.9781476f, 0.9816272f, 0.9848078f, 0.9876883f, 0.9902681f, 0.9925462f,
834 0.9945219f, 0.9961947f, 0.9975641f, 0.9986295f, 0.9993908f, 0.9998477f,
840 icvSinCos( int angle, float *cosval, float *sinval )
842 angle += (angle < 0 ? 360 : 0);
843 *sinval = icvSinTable[angle];
844 *cosval = icvSinTable[450 - angle];
848 constructs polygon that represents elliptic arc.
851 cvEllipse2Poly( CvPoint center, CvSize axes, int angle,
852 int arc_start, int arc_end, CvPoint* pts, int delta )
855 double size_a = axes.width, size_b = axes.height;
856 double cx = center.x, cy = center.y;
857 CvPoint *pts_origin = pts;
865 if( arc_start > arc_end )
871 while( arc_start < 0 )
876 while( arc_end > 360 )
881 if( arc_end - arc_start > 360 )
886 icvSinCos( angle, &alpha, &beta );
888 for( i = arc_start; i < arc_end + delta; i += delta )
892 if( angle > arc_end )
897 x = size_a * icvSinTable[450-angle];
898 y = size_b * icvSinTable[angle];
899 pts->x = cvRound( cx + x * alpha - y * beta );
900 pts->y = cvRound( cy - x * beta - y * alpha );
901 pts += i == arc_start || pts->x != pts[-1].x || pts->y != pts[-1].y;
904 i = (int)(pts - pts_origin);
906 pts_origin[i] = pts_origin[i-1];
912 icvEllipseEx( CvMat* img, CvPoint center, CvSize axes,
913 int angle, int arc_start, int arc_end,
914 const void* color, int thickness, int line_type )
916 CvMemStorage* st = 0;
918 CV_FUNCNAME( "icvEllipseEx" );
925 if( axes.width < 0 || axes.height < 0 )
926 CV_ERROR( CV_StsBadSize, "" );
928 delta = (MAX(axes.width,axes.height)+(XY_ONE>>1))>>XY_SHIFT;
929 delta = delta < 3 ? 90 : delta < 10 ? 30 : delta < 15 ? 18 : 5;
931 count = cvEllipse2Poly( center, axes, angle, arc_start, arc_end, v, delta );
935 icvPolyLine( img, v, count, 0, color, thickness, line_type, XY_SHIFT );
937 else if( arc_end - arc_start >= 360 )
939 icvFillConvexPoly( img, v, count, color, line_type, XY_SHIFT );
947 CV_CALL( st = cvCreateMemStorage( CV_DRAWING_STORAGE_BLOCK ));
948 CV_CALL( edges = (CvContour*)cvCreateSeq( 0, sizeof(CvContour), sizeof(CvPolyEdge), st ));
951 CV_CALL( cvMakeSeqHeaderForArray( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint),
952 v, count, &vtx, &block ));
954 CV_CALL( icvCollectPolyEdges( img, &vtx, edges, color, line_type, XY_SHIFT ));
955 CV_CALL( icvFillEdgeCollection( img, edges, color ));
961 cvReleaseMemStorage( &st );
965 /****************************************************************************************\
967 \****************************************************************************************/
969 /* helper macros: filling horizontal row */
970 #define ICV_HLINE( ptr, xl, xr, color, pix_size ) \
972 uchar* hline_ptr = (uchar*)(ptr) + (xl)*(pix_size); \
973 uchar* hline_max_ptr = (uchar*)(ptr) + (xr)*(pix_size); \
975 for( ; hline_ptr <= hline_max_ptr; hline_ptr += (pix_size))\
978 for( hline_j = 0; hline_j < (pix_size); hline_j++ ) \
980 hline_ptr[hline_j] = ((uchar*)color)[hline_j]; \
986 /* filling convex polygon. v - array of vertices, ntps - number of points */
988 icvFillConvexPoly( CvMat* img, CvPoint *v, int npts, const void* color, int line_type, int shift )
997 int delta = shift ? 1 << (shift - 1) : 0;
998 int i, y, imin = 0, left = 0, right = 1, x1, x2;
1000 int xmin, xmax, ymin, ymax;
1001 uchar* ptr = img->data.ptr;
1002 CvSize size = cvGetMatSize( img );
1003 int pix_size = CV_ELEM_SIZE(img->type);
1007 if( line_type < CV_AA )
1008 delta1 = delta2 = XY_ONE >> 1;
1009 //delta1 = 0, delta2 = XY_ONE - 1;
1011 delta1 = XY_ONE - 1, delta2 = 0;
1014 p0.x <<= XY_SHIFT - shift;
1015 p0.y <<= XY_SHIFT - shift;
1017 assert( 0 <= shift && shift <= XY_SHIFT );
1018 xmin = xmax = v[0].x;
1019 ymin = ymax = v[0].y;
1021 for( i = 0; i < npts; i++ )
1030 ymax = MAX( ymax, p.y );
1031 xmax = MAX( xmax, p.x );
1032 xmin = MIN( xmin, p.x );
1034 p.x <<= XY_SHIFT - shift;
1035 p.y <<= XY_SHIFT - shift;
1037 if( line_type <= 8 )
1042 pt0.x = p0.x >> XY_SHIFT;
1043 pt0.y = p0.y >> XY_SHIFT;
1044 pt1.x = p.x >> XY_SHIFT;
1045 pt1.y = p.y >> XY_SHIFT;
1046 icvLine( img, pt0, pt1, color, line_type );
1049 icvLine2( img, p0, p, color );
1052 icvLineAA( img, p0, p, color );
1056 xmin = (xmin + delta) >> shift;
1057 xmax = (xmax + delta) >> shift;
1058 ymin = (ymin + delta) >> shift;
1059 ymax = (ymax + delta) >> shift;
1061 if( npts < 3 || xmax < 0 || ymax < 0 || xmin >= size.width || ymin >= size.height )
1064 ymax = MIN( ymax, size.height - 1 );
1065 edge[0].idx = edge[1].idx = imin;
1067 edge[0].ye = edge[1].ye = y = ymin;
1069 edge[1].di = npts - 1;
1075 if( line_type < CV_AA || y < ymax || y == ymin )
1077 for( i = 0; i < 2; i++ )
1079 if( y >= edge[i].ye )
1081 int idx = edge[i].idx, di = edge[i].di;
1082 int xs = 0, xe, ye, ty = 0;
1086 ty = (v[idx].y + delta) >> shift;
1087 if( ty > y || edges == 0 )
1091 idx -= ((idx < npts) - 1) & npts; /* idx -= idx >= npts ? npts : 0 */
1096 xs <<= XY_SHIFT - shift;
1097 xe = v[idx].x << (XY_SHIFT - shift);
1104 edge[i].dx = ((xe - xs)*2 + (ye - y)) / (2 * (ye - y));
1111 if( edge[left].x > edge[right].x )
1122 int xx1 = (x1 + delta1) >> XY_SHIFT;
1123 int xx2 = (x2 + delta2) >> XY_SHIFT;
1125 if( xx2 >= 0 && xx1 < size.width )
1129 if( xx2 >= size.width )
1130 xx2 = size.width - 1;
1131 ICV_HLINE( ptr, xx1, xx2, color, pix_size );
1135 x1 += edge[left].dx;
1136 x2 += edge[right].dx;
1142 while( ++y <= ymax );
1146 /******** Arbitrary polygon **********/
1149 icvCollectPolyEdges( CvMat* img, CvSeq* v, CvContour* edges,
1150 const void* color, int line_type, int shift,
1153 int i, count = v->total;
1154 CvRect bounds = edges->rect;
1155 int delta = offset.y + (shift ? 1 << (shift - 1) : 0);
1156 int elem_type = CV_MAT_TYPE(v->flags);
1161 cvStartReadSeq( v, &reader );
1162 cvStartAppendToSeq( (CvSeq*)edges, &writer );
1164 for( i = 0; i < count; i++ )
1166 CvPoint pt0, pt1, t0, t1;
1168 CV_READ_EDGE( pt0, pt1, reader );
1170 if( elem_type == CV_32SC2 )
1172 pt0.x = (pt0.x + offset.x) << (XY_SHIFT - shift);
1173 pt0.y = (pt0.y + delta) >> shift;
1174 pt1.x = (pt1.x + offset.x) << (XY_SHIFT - shift);
1175 pt1.y = (pt1.y + delta) >> shift;
1180 assert( shift == 0 );
1182 x.i = pt0.x; y.i = pt0.y;
1183 pt0.x = cvRound((x.f + offset.x) * XY_ONE);
1184 pt0.y = cvRound(y.f + offset.y);
1185 x.i = pt1.x; y.i = pt1.y;
1186 pt1.x = cvRound((x.f + offset.x) * XY_ONE);
1187 pt1.y = cvRound(y.f + offset.y);
1190 if( line_type < CV_AA )
1192 t0.y = pt0.y; t1.y = pt1.y;
1193 t0.x = (pt0.x + (XY_ONE >> 1)) >> XY_SHIFT;
1194 t1.x = (pt1.x + (XY_ONE >> 1)) >> XY_SHIFT;
1195 icvLine( img, t0, t1, color, line_type );
1199 t0.x = pt0.x; t1.x = pt1.x;
1200 t0.y = pt0.y << XY_SHIFT;
1201 t1.y = pt1.y << XY_SHIFT;
1202 icvLineAA( img, t0, t1, color );
1205 if( pt0.y == pt1.y )
1209 CV_SWAP( pt0, pt1, t0 );
1211 bounds.y = MIN( bounds.y, pt0.y );
1212 bounds.height = MAX( bounds.height, pt1.y );
1216 bounds.x = MIN( bounds.x, pt0.x );
1217 bounds.width = MAX( bounds.width, pt1.x );
1221 bounds.x = MIN( bounds.x, pt1.x );
1222 bounds.width = MAX( bounds.width, pt0.x );
1228 edge.dx = (pt1.x - pt0.x) / (pt1.y - pt0.y);
1229 assert( edge.y0 < edge.y1 );
1231 CV_WRITE_SEQ_ELEM( edge, writer );
1234 edges->rect = bounds;
1235 cvEndWriteSeq( &writer );
1239 icvCmpEdges( const void* _e1, const void* _e2, void* /*userdata*/ )
1241 CvPolyEdge *e1 = (CvPolyEdge*)_e1, *e2 = (CvPolyEdge*)_e2;
1242 return e1->y0 - e2->y0 ? e1->y0 - e2->y0 :
1243 e1->x - e2->x ? e1->x - e2->x : e1->dx - e2->dx;
1246 /**************** helper macros and functions for sequence/contour processing ***********/
1249 icvFillEdgeCollection( CvMat* img, CvContour* edges, const void* color )
1252 int i, y, total = edges->total;
1254 CvSize size = cvGetMatSize(img);
1256 int y_max = INT_MIN;
1257 int pix_size = CV_ELEM_SIZE(img->type);
1261 memset( &tmp, 0, sizeof(tmp));
1263 /* check parameters */
1264 if( edges->total < 2 || edges->rect.height < 0 || edges->rect.y >= size.height ||
1265 edges->rect.width < 0 || edges->rect.x >= size.width )
1268 cvSeqSort( (CvSeq*)edges, icvCmpEdges, 0 );
1269 cvStartReadSeq( (CvSeq*)edges, &reader );
1276 for( i = 0; i < total; i++ )
1278 CvPolyEdge* e1 = (CvPolyEdge*)(reader.ptr);
1281 assert( e1->y0 < e1->y1 && (i == 0 || icvCmpEdges( e, e1, 0 ) <= 0) );
1284 y_max = MAX( y_max, e1->y1 );
1286 CV_NEXT_SEQ_ELEM( sizeof(CvPolyEdge), reader );
1291 cvSeqPush( (CvSeq*)edges, &tmp );
1295 cvStartReadSeq( (CvSeq*)edges, &reader );
1296 e = (CvPolyEdge*)(reader.ptr);
1297 y_max = MIN( y_max, size.height );
1299 for( y = e->y0; y < y_max; y++ )
1301 CvPolyEdge *last, *prelast, *keep_prelast;
1304 int clipline = y < 0;
1308 while( last || e->y0 == y )
1310 if( last && last->y1 == y )
1312 /* exlude edge if y reachs its lower point */
1313 prelast->next = last->next;
1317 keep_prelast = prelast;
1318 if( last && (e->y0 > y || last->x < e->x) )
1320 /* go to the next edge in active list */
1324 else if( i < total )
1326 /* insert new edge into active list if y reachs its upper point */
1330 CV_NEXT_SEQ_ELEM( edges->elem_size, reader );
1331 e = (CvPolyEdge*)(reader.ptr);
1341 /* convert x's from fixed-point to image coordinates */
1342 uchar *timg = (uchar*)(img->data.ptr) + y * img->step;
1343 int x1 = keep_prelast->x;
1344 int x2 = prelast->x;
1354 x1 = (x1 + XY_ONE - 1) >> XY_SHIFT;
1355 x2 = x2 >> XY_SHIFT;
1357 /* clip and draw the line */
1358 if( x1 < size.width && x2 >= 0 )
1362 if( x2 >= size.width )
1363 x2 = size.width - 1;
1364 ICV_HLINE( timg, x1, x2, color, pix_size );
1367 keep_prelast->x += keep_prelast->dx;
1368 prelast->x += prelast->dx;
1373 /* sort edges (bubble sort on list) */
1381 while( last != keep_prelast && last->next != 0 )
1383 CvPolyEdge *te = last->next;
1386 if( last->x > te->x )
1389 last->next = te->next;
1400 keep_prelast = prelast;
1402 while( sort_flag && keep_prelast != tmp.next && keep_prelast != &tmp );
1409 /* draws simple or filled circle */
1411 icvCircle( CvMat* img, CvPoint center, int radius, const void* color, int fill )
1413 CvSize size = cvGetMatSize( img );
1414 int step = img->step;
1415 int pix_size = CV_ELEM_SIZE(img->type);
1416 uchar* ptr = (uchar*)(img->data.ptr);
1417 int err = 0, dx = radius, dy = 0, plus = 1, minus = (radius << 1) - 1;
1418 int inside = center.x >= radius && center.x < size.width - radius &&
1419 center.y >= radius && center.y < size.height - radius;
1421 #define ICV_PUT_POINT( ptr, x ) \
1422 CV_MEMCPY_CHAR( ptr + (x)*pix_size, color, pix_size );
1427 int y11 = center.y - dy, y12 = center.y + dy, y21 = center.y - dx, y22 = center.y + dx;
1428 int x11 = center.x - dx, x12 = center.x + dx, x21 = center.x - dy, x22 = center.x + dy;
1432 uchar *tptr0 = ptr + y11 * step;
1433 uchar *tptr1 = ptr + y12 * step;
1437 ICV_PUT_POINT( tptr0, x11 );
1438 ICV_PUT_POINT( tptr1, x11 );
1439 ICV_PUT_POINT( tptr0, x12 );
1440 ICV_PUT_POINT( tptr1, x12 );
1444 ICV_HLINE( tptr0, x11, x12, color, pix_size );
1445 ICV_HLINE( tptr1, x11, x12, color, pix_size );
1448 tptr0 = ptr + y21 * step;
1449 tptr1 = ptr + y22 * step;
1453 ICV_PUT_POINT( tptr0, x21 );
1454 ICV_PUT_POINT( tptr1, x21 );
1455 ICV_PUT_POINT( tptr0, x22 );
1456 ICV_PUT_POINT( tptr1, x22 );
1460 ICV_HLINE( tptr0, x21, x22, color, pix_size );
1461 ICV_HLINE( tptr1, x21, x22, color, pix_size );
1464 else if( x11 < size.width && x12 >= 0 && y21 < size.height && y22 >= 0 )
1468 x11 = MAX( x11, 0 );
1469 x12 = MIN( x12, size.width - 1 );
1472 if( (unsigned)y11 < (unsigned)size.height )
1474 uchar *tptr = ptr + y11 * step;
1479 ICV_PUT_POINT( tptr, x11 );
1480 if( x12 < size.width )
1481 ICV_PUT_POINT( tptr, x12 );
1484 ICV_HLINE( tptr, x11, x12, color, pix_size );
1487 if( (unsigned)y12 < (unsigned)size.height )
1489 uchar *tptr = ptr + y12 * step;
1494 ICV_PUT_POINT( tptr, x11 );
1495 if( x12 < size.width )
1496 ICV_PUT_POINT( tptr, x12 );
1499 ICV_HLINE( tptr, x11, x12, color, pix_size );
1502 if( x21 < size.width && x22 >= 0 )
1506 x21 = MAX( x21, 0 );
1507 x22 = MIN( x22, size.width - 1 );
1510 if( (unsigned)y21 < (unsigned)size.height )
1512 uchar *tptr = ptr + y21 * step;
1517 ICV_PUT_POINT( tptr, x21 );
1518 if( x22 < size.width )
1519 ICV_PUT_POINT( tptr, x22 );
1522 ICV_HLINE( tptr, x21, x22, color, pix_size );
1525 if( (unsigned)y22 < (unsigned)size.height )
1527 uchar *tptr = ptr + y22 * step;
1532 ICV_PUT_POINT( tptr, x21 );
1533 if( x22 < size.width )
1534 ICV_PUT_POINT( tptr, x22 );
1537 ICV_HLINE( tptr, x21, x22, color, pix_size );
1545 mask = (err <= 0) - 1;
1547 err -= minus & mask;
1552 #undef ICV_PUT_POINT
1557 icvThickLine( CvMat* img, CvPoint p0, CvPoint p1, const void* color,
1558 int thickness, int line_type, int flags, int shift )
1560 static const double INV_XY_ONE = 1./XY_ONE;
1562 p0.x <<= XY_SHIFT - shift;
1563 p0.y <<= XY_SHIFT - shift;
1564 p1.x <<= XY_SHIFT - shift;
1565 p1.y <<= XY_SHIFT - shift;
1567 if( thickness <= 1 )
1569 if( line_type < CV_AA )
1571 if( line_type == 1 || line_type == 4 || shift == 0 )
1573 p0.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT;
1574 p0.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT;
1575 p1.x = (p1.x + (XY_ONE>>1)) >> XY_SHIFT;
1576 p1.y = (p1.y + (XY_ONE>>1)) >> XY_SHIFT;
1577 icvLine( img, p0, p1, color, line_type );
1580 icvLine2( img, p0, p1, color );
1583 icvLineAA( img, p0, p1, color );
1587 CvPoint pt[4], dp = {0,0};
1588 double dx = (p0.x - p1.x)*INV_XY_ONE, dy = (p1.y - p0.y)*INV_XY_ONE;
1589 double r = dx * dx + dy * dy;
1591 thickness <<= XY_SHIFT - 1;
1593 if( fabs(r) > DBL_EPSILON )
1595 r = thickness * cvInvSqrt( (float) r );
1596 dp.x = cvRound( dy * r );
1597 dp.y = cvRound( dx * r );
1600 pt[0].x = p0.x + dp.x;
1601 pt[0].y = p0.y + dp.y;
1602 pt[1].x = p0.x - dp.x;
1603 pt[1].y = p0.y - dp.y;
1604 pt[2].x = p1.x - dp.x;
1605 pt[2].y = p1.y - dp.y;
1606 pt[3].x = p1.x + dp.x;
1607 pt[3].y = p1.y + dp.y;
1609 icvFillConvexPoly( img, pt, 4, color, line_type, XY_SHIFT );
1611 for( i = 0; i < 2; i++ )
1615 if( line_type < CV_AA )
1618 center.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT;
1619 center.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT;
1620 icvCircle( img, center, thickness >> XY_SHIFT, color, 1 );
1624 icvEllipseEx( img, p0, cvSize(thickness, thickness),
1625 0, 0, 360, color, -1, line_type );
1635 icvPolyLine( CvMat* img, CvPoint *v, int count, int is_closed,
1636 const void* color, int thickness,
1637 int line_type, int shift )
1639 CV_FUNCNAME("icvPolyLine");
1645 int i = is_closed ? count - 1 : 0;
1646 int flags = 2 + !is_closed;
1648 assert( 0 <= shift && shift <= XY_SHIFT );
1649 assert( img && thickness >= 0 );
1650 assert( v && count >= 0 );
1653 CV_ERROR( CV_StsNullPtr, "" );
1656 for( i = !is_closed; i < count; i++ )
1659 icvThickLine( img, p0, p, color, thickness, line_type, flags, shift );
1668 /****************************************************************************************\
1669 * External functions *
1670 \****************************************************************************************/
1672 CV_IMPL CvScalar cvColorToScalar( double packed_color, int type )
1676 if( CV_MAT_DEPTH( type ) == CV_8U )
1678 int icolor = cvRound( packed_color );
1679 if( CV_MAT_CN( type ) > 1 )
1681 scalar.val[0] = icolor & 255;
1682 scalar.val[1] = (icolor >> 8) & 255;
1683 scalar.val[2] = (icolor >> 16) & 255;
1684 scalar.val[3] = (icolor >> 24) & 255;
1688 scalar.val[0] = CV_CAST_8U( icolor );
1689 scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
1692 else if( CV_MAT_DEPTH( type ) == CV_8S )
1694 int icolor = cvRound( packed_color );
1695 if( CV_MAT_CN( type ) > 1 )
1697 scalar.val[0] = (char)icolor;
1698 scalar.val[1] = (char)(icolor >> 8);
1699 scalar.val[2] = (char)(icolor >> 16);
1700 scalar.val[3] = (char)(icolor >> 24);
1704 scalar.val[0] = CV_CAST_8S( icolor );
1705 scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
1710 int cn = CV_MAT_CN( type );
1714 scalar.val[0] = packed_color;
1715 scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
1718 scalar.val[0] = scalar.val[1] = packed_color;
1719 scalar.val[2] = scalar.val[3] = 0;
1722 scalar.val[0] = scalar.val[1] = scalar.val[2] = packed_color;
1726 scalar.val[0] = scalar.val[1] =
1727 scalar.val[2] = scalar.val[3] = packed_color;
1737 cvLine( void* img, CvPoint pt1, CvPoint pt2, CvScalar color,
1738 int thickness, int line_type, int shift )
1740 CV_FUNCNAME( "cvLine" );
1745 CvMat stub, *mat = (CvMat*)img;
1748 CV_CALL( mat = cvGetMat( img, &stub, &coi ));
1750 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
1754 CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
1756 if( (unsigned)thickness > 255 )
1757 CV_ERROR( CV_StsOutOfRange, "" );
1759 if( shift < 0 || XY_SHIFT < shift )
1760 CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" );
1762 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
1763 icvThickLine( mat, pt1, pt2, buf, thickness, line_type, 3, shift );
1770 cvRectangle( void* img, CvPoint pt1, CvPoint pt2,
1771 CvScalar color, int thickness,
1772 int line_type, int shift )
1776 CV_FUNCNAME("cvRectangle");
1781 CvMat stub, *mat = (CvMat*)img;
1784 if( thickness > 255 )
1785 CV_ERROR( CV_StsOutOfRange, "" );
1787 CV_CALL( mat = cvGetMat( img, &stub, &coi ));
1789 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
1793 CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
1795 if( shift < 0 || XY_SHIFT < shift )
1796 CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" );
1798 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
1807 if( thickness >= 0 )
1808 icvPolyLine( mat, pt, 4, 1, buf, thickness, line_type, shift );
1810 icvFillConvexPoly( mat, pt, 4, buf, line_type, shift );
1817 cvCircle( void *img, CvPoint center, int radius,
1818 CvScalar color, int thickness, int line_type, int shift )
1820 CV_FUNCNAME( "cvCircle" );
1825 CvMat stub, *mat = (CvMat*)img;
1828 CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
1830 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
1834 CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
1837 CV_ERROR( CV_StsOutOfRange, "" );
1839 if( thickness > 255 )
1840 CV_ERROR( CV_StsOutOfRange, "" );
1842 if( shift < 0 || XY_SHIFT < shift )
1843 CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" );
1845 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
1847 if( thickness > 1 || line_type >= CV_AA )
1849 center.x <<= XY_SHIFT - shift;
1850 center.y <<= XY_SHIFT - shift;
1851 radius <<= XY_SHIFT - shift;
1852 icvEllipseEx( mat, center, cvSize( radius, radius ),
1853 0, 0, 360, buf, thickness, line_type );
1857 icvCircle( mat, center, radius, buf, thickness < 0 );
1865 cvEllipse( void *img, CvPoint center, CvSize axes,
1866 double angle, double start_angle, double end_angle,
1867 CvScalar color, int thickness, int line_type, int shift )
1869 CV_FUNCNAME( "cvEllipse" );
1874 CvMat stub, *mat = (CvMat*)img;
1877 CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
1879 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
1883 CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
1885 if( axes.width < 0 || axes.height < 0 )
1886 CV_ERROR( CV_StsOutOfRange, "" );
1888 if( thickness > 255 )
1889 CV_ERROR( CV_StsOutOfRange, "" );
1891 if( shift < 0 || XY_SHIFT < shift )
1892 CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" );
1894 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
1897 int _angle = cvRound(angle);
1898 int _start_angle = cvRound(start_angle);
1899 int _end_angle = cvRound(end_angle);
1900 center.x <<= XY_SHIFT - shift;
1901 center.y <<= XY_SHIFT - shift;
1902 axes.width <<= XY_SHIFT - shift;
1903 axes.height <<= XY_SHIFT - shift;
1905 CV_CALL( icvEllipseEx( mat, center, axes, _angle, _start_angle,
1906 _end_angle, buf, thickness, line_type ));
1914 cvFillConvexPoly( void *img, CvPoint *pts, int npts, CvScalar color, int line_type, int shift )
1916 CV_FUNCNAME( "cvFillConvexPoly" );
1921 CvMat stub, *mat = (CvMat*)img;
1924 CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
1926 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
1930 CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
1933 CV_ERROR( CV_StsNullPtr, "" );
1936 CV_ERROR( CV_StsOutOfRange, "" );
1938 if( shift < 0 || XY_SHIFT < shift )
1939 CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" );
1941 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
1942 icvFillConvexPoly( mat, pts, npts, buf, line_type, shift );
1949 cvFillPoly( void *img, CvPoint **pts, int *npts, int contours,
1950 CvScalar color, int line_type, int shift )
1952 CvMemStorage* st = 0;
1954 CV_FUNCNAME( "cvFillPoly" );
1959 CvMat stub, *mat = (CvMat*)img;
1962 CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
1964 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
1968 CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
1971 CV_ERROR( CV_StsBadArg, "" );
1974 CV_ERROR( CV_StsNullPtr, "" );
1977 CV_ERROR( CV_StsNullPtr, "" );
1979 if( shift < 0 || XY_SHIFT < shift )
1980 CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" );
1982 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
1985 CvContour* edges = 0;
1989 CV_CALL( st = cvCreateMemStorage( CV_DRAWING_STORAGE_BLOCK ));
1990 CV_CALL( edges = (CvContour*)cvCreateSeq( 0, sizeof(CvContour),
1991 sizeof(CvPolyEdge), st ));
1993 for( int i = 0; i < contours; i++ )
1996 CV_ERROR( CV_StsNullPtr, "" );
1999 CV_ERROR( CV_StsOutOfRange, "" );
2001 cvMakeSeqHeaderForArray( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint),
2002 pts[i], npts[i], &vtx, &block );
2004 CV_CALL( icvCollectPolyEdges( mat, &vtx, edges, buf, line_type, shift ));
2007 CV_CALL( icvFillEdgeCollection( mat, edges, buf ));
2012 cvReleaseMemStorage( &st );
2018 cvPolyLine( void *img, CvPoint **pts, int *npts,
2019 int contours, int closed, CvScalar color,
2020 int thickness, int line_type, int shift )
2022 CV_FUNCNAME( "cvPolyLine" );
2027 CvMat stub, *mat = (CvMat*)img;
2030 CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
2032 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
2036 CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
2039 CV_ERROR( CV_StsBadArg, "" );
2041 if( thickness < -1 || thickness > 255 )
2042 CV_ERROR( CV_StsBadArg, "" );
2045 CV_ERROR( CV_StsNullPtr, "" );
2048 CV_ERROR( CV_StsNullPtr, "" );
2050 if( shift < 0 || XY_SHIFT < shift )
2051 CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" );
2053 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
2055 for( i = 0; i < contours; i++ )
2056 icvPolyLine( mat, pts[i], npts[i], closed, buf, thickness, line_type, shift );
2062 #define CV_FONT_SIZE_SHIFT 8
2063 #define CV_FONT_ITALIC_ALPHA (1 << 8)
2064 #define CV_FONT_ITALIC_DIGIT (2 << 8)
2065 #define CV_FONT_ITALIC_PUNCT (4 << 8)
2066 #define CV_FONT_ITALIC_BRACES (8 << 8)
2067 #define CV_FONT_HAVE_GREEK (16 << 8)
2068 #define CV_FONT_HAVE_CYRILLIC (32 << 8)
2070 static const int icvHersheyPlain[] = {
2071 (5 + 4*16) + CV_FONT_HAVE_GREEK,
2072 199, 214, 217, 233, 219, 197, 234, 216, 221, 222, 228, 225, 211, 224, 210, 220,
2073 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 212, 213, 191, 226, 192,
2074 215, 190, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
2075 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 193, 84,
2076 194, 85, 86, 87, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
2077 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
2078 195, 223, 196, 88 };
2080 static const int icvHersheyPlainItalic[] = {
2081 (5 + 4*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_HAVE_GREEK,
2082 199, 214, 217, 233, 219, 197, 234, 216, 221, 222, 228, 225, 211, 224, 210, 220,
2083 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 212, 213, 191, 226, 192,
2084 215, 190, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
2085 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 193, 84,
2086 194, 85, 86, 87, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
2087 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
2088 195, 223, 196, 88 };
2090 static const int icvHersheyComplexSmall[] = {
2091 (6 + 7*16) + CV_FONT_HAVE_GREEK,
2092 1199, 1214, 1217, 1275, 1274, 1271, 1272, 1216, 1221, 1222, 1219, 1232, 1211, 1231, 1210, 1220,
2093 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1212, 2213, 1241, 1238, 1242,
2094 1215, 1273, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013,
2095 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1223, 1084,
2096 1224, 1247, 586, 1249, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
2097 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126,
2098 1225, 1229, 1226, 1246 };
2100 static const int icvHersheyComplexSmallItalic[] = {
2101 (6 + 7*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_HAVE_GREEK,
2102 1199, 1214, 1217, 1275, 1274, 1271, 1272, 1216, 1221, 1222, 1219, 1232, 1211, 1231, 1210, 1220,
2103 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1212, 1213, 1241, 1238, 1242,
2104 1215, 1273, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063,
2105 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1223, 1084,
2106 1224, 1247, 586, 1249, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161,
2107 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176,
2108 1225, 1229, 1226, 1246 };
2110 static const int icvHersheySimplex[] = {
2111 (9 + 12*16) + CV_FONT_HAVE_GREEK,
2112 2199, 714, 717, 733, 719, 697, 734, 716, 721, 722, 728, 725, 711, 724, 710, 720,
2113 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 712, 713, 691, 726, 692,
2114 715, 690, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513,
2115 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 693, 584,
2116 694, 2247, 586, 2249, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611,
2117 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626,
2118 695, 723, 696, 2246 };
2120 static const int icvHersheyDuplex[] = {
2121 (9 + 12*16) + CV_FONT_HAVE_GREEK,
2122 2199, 2714, 2728, 2732, 2719, 2733, 2718, 2727, 2721, 2722, 2723, 2725, 2711, 2724, 2710, 2720,
2123 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2712, 2713, 2730, 2726, 2731,
2124 2715, 2734, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513,
2125 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2223, 2084,
2126 2224, 2247, 587, 2249, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611,
2127 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626,
2128 2225, 2229, 2226, 2246 };
2130 static const int icvHersheyComplex[] = {
2131 (9 + 12*16) + CV_FONT_HAVE_GREEK + CV_FONT_HAVE_CYRILLIC,
2132 2199, 2214, 2217, 2275, 2274, 2271, 2272, 2216, 2221, 2222, 2219, 2232, 2211, 2231, 2210, 2220,
2133 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2212, 2213, 2241, 2238, 2242,
2134 2215, 2273, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013,
2135 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2223, 2084,
2136 2224, 2247, 587, 2249, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111,
2137 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126,
2138 2225, 2229, 2226, 2246 };
2140 static const int icvHersheyComplexItalic[] = {
2141 (9 + 12*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_ITALIC_DIGIT + CV_FONT_ITALIC_PUNCT +
2142 CV_FONT_HAVE_GREEK + CV_FONT_HAVE_CYRILLIC,
2143 2199, 2764, 2778, 2782, 2769, 2783, 2768, 2777, 2771, 2772, 2219, 2232, 2211, 2231, 2210, 2220,
2144 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2212, 2213, 2241, 2238, 2242,
2145 2765, 2273, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063,
2146 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2223, 2084,
2147 2224, 2247, 587, 2249, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161,
2148 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176,
2149 2225, 2229, 2226, 2246 };
2151 static const int icvHersheyTriplex[] = {
2152 (9 + 12*16) + CV_FONT_HAVE_GREEK,
2153 2199, 3214, 3228, 3232, 3219, 3233, 3218, 3227, 3221, 3222, 3223, 3225, 3211, 3224, 3210, 3220,
2154 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3212, 3213, 3230, 3226, 3231,
2155 3215, 3234, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013,
2156 2014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 2223, 2084,
2157 2224, 2247, 587, 2249, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111,
2158 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126,
2159 2225, 2229, 2226, 2246 };
2161 static const int icvHersheyTriplexItalic[] = {
2162 (9 + 12*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_ITALIC_DIGIT +
2163 CV_FONT_ITALIC_PUNCT + CV_FONT_HAVE_GREEK,
2164 2199, 3264, 3278, 3282, 3269, 3233, 3268, 3277, 3271, 3272, 3223, 3225, 3261, 3224, 3260, 3270,
2165 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3262, 3263, 3230, 3226, 3231,
2166 3265, 3234, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063,
2167 2064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 2223, 2084,
2168 2224, 2247, 587, 2249, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161,
2169 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176,
2170 2225, 2229, 2226, 2246 };
2172 static const int icvHersheyScriptSimplex[] = {
2173 (9 + 12*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_HAVE_GREEK,
2174 2199, 714, 717, 733, 719, 697, 734, 716, 721, 722, 728, 725, 711, 724, 710, 720,
2175 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 712, 713, 691, 726, 692,
2176 715, 690, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563,
2177 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 693, 584,
2178 694, 2247, 586, 2249, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661,
2179 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676,
2180 695, 723, 696, 2246 };
2182 static const int icvHersheyScriptComplex[] = {
2183 (9 + 12*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_ITALIC_DIGIT + CV_FONT_ITALIC_PUNCT + CV_FONT_HAVE_GREEK,
2184 2199, 2764, 2778, 2782, 2769, 2783, 2768, 2777, 2771, 2772, 2219, 2232, 2211, 2231, 2210, 2220,
2185 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2212, 2213, 2241, 2238, 2242,
2186 2215, 2273, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562, 2563,
2187 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2223, 2084,
2188 2224, 2247, 586, 2249, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661,
2189 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676,
2190 2225, 2229, 2226, 2246 };
2194 cvPutText( void *img, const char *text, CvPoint org, const CvFont *font, CvScalar color )
2196 CV_FUNCNAME( "cvPutText" );
2202 int top_bottom = 0, base_line;
2203 int hscale, vscale, default_shear, italic_shear;
2204 int thickness, line_type;
2205 CvMat stub, *mat = (CvMat*)img;
2207 CvPoint pt[1 << 10];
2211 const char **faces = icvHersheyGlyphs;
2213 CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
2216 CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
2218 if( CV_IS_IMAGE_HDR(img) && ((IplImage*)img)->origin )
2221 if( !text || !font || !font->ascii )
2222 CV_ERROR( CV_StsNullPtr, "" );
2224 CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
2225 base_line = -(font->ascii[0] & 15);
2226 hscale = cvRound(font->hscale*XY_ONE);
2227 vscale = cvRound(font->vscale*XY_ONE);
2228 default_shear = cvRound(font->shear*font->vscale*XY_ONE);
2229 italic_shear = !(font->font_face & CV_FONT_ITALIC) ? 0 : cvRound(font->vscale*.25*XY_ONE);
2230 thickness = font->thickness;
2231 line_type = font->line_type;
2233 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
2239 view_x = org.x << XY_SHIFT;
2240 view_y = (org.y << XY_SHIFT) + base_line*vscale;
2242 for( i = 0; text[i] != '\0'; i++ )
2244 int c = (uchar)text[i];
2245 int dx, shear = default_shear;
2249 if( c > 128 || c < ' ' )
2254 if( ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
2256 if( !(font->ascii[0] & CV_FONT_ITALIC_ALPHA) )
2257 shear += italic_shear;
2259 else if( '0' <= c && c <= '9' )
2261 if( !(font->ascii[0] & CV_FONT_ITALIC_DIGIT) )
2262 shear += italic_shear;
2266 if( !(font->ascii[0] & CV_FONT_ITALIC_PUNCT) )
2267 shear += italic_shear;
2271 shear += italic_shear;
2275 ptr = faces[font->ascii[(c-' ')+1]];
2276 p.x = (unsigned char)ptr[0] - 'R';
2277 p.y = (unsigned char)ptr[1] - 'R';
2279 view_x -= p.x*hscale;
2284 if( *ptr == ' ' || !*ptr )
2287 icvPolyLine( mat, pt, count, 0, buf, thickness, line_type, XY_SHIFT );
2294 p.x = (unsigned char)ptr[0] - 'R';
2295 p.y = (unsigned char)ptr[1] - 'R';
2297 pt[count].x = p.x*hscale - p.y*shear + view_x;
2298 pt[count++].y = p.y*vscale + view_y;
2308 cvInitFont( CvFont *font, int font_face, double hscale, double vscale,
2309 double shear, int thickness, int line_type )
2311 CV_FUNCNAME( "cvInitFont" );
2315 int is_italic = font_face & CV_FONT_ITALIC;
2318 CV_ERROR( CV_StsNullPtr, "" );
2320 if( hscale <= 0 || vscale <= 0 || thickness < 0 )
2321 CV_ERROR( CV_StsOutOfRange, "" );
2323 switch( (font_face & 7) )
2325 case CV_FONT_HERSHEY_SIMPLEX:
2326 font->ascii = icvHersheySimplex;
2328 case CV_FONT_HERSHEY_PLAIN:
2329 font->ascii = !is_italic ? icvHersheyPlain : icvHersheyPlainItalic;
2331 case CV_FONT_HERSHEY_DUPLEX:
2332 font->ascii = icvHersheyDuplex;
2334 case CV_FONT_HERSHEY_COMPLEX:
2335 font->ascii = !is_italic ? icvHersheyComplex : icvHersheyComplexItalic;
2337 case CV_FONT_HERSHEY_TRIPLEX:
2338 font->ascii = !is_italic ? icvHersheyTriplex : icvHersheyTriplexItalic;
2340 case CV_FONT_HERSHEY_COMPLEX_SMALL:
2341 font->ascii = !is_italic ? icvHersheyComplexSmall : icvHersheyComplexSmallItalic;
2343 case CV_FONT_HERSHEY_SCRIPT_SIMPLEX:
2344 font->ascii = icvHersheyScriptSimplex;
2346 case CV_FONT_HERSHEY_SCRIPT_COMPLEX:
2347 font->ascii = icvHersheyScriptComplex;
2350 CV_ERROR( CV_StsOutOfRange, "Unknown font type" );
2353 font->font_face = font_face;
2354 font->hscale = (float)hscale;
2355 font->vscale = (float)vscale;
2356 font->thickness = thickness;
2357 font->shear = (float)shear;
2358 font->greek = font->cyrillic = 0;
2359 font->line_type = line_type;
2366 cvGetTextSize( const char *text, const CvFont *font, CvSize *size, int *_base_line )
2368 CV_FUNCNAME( "cvGetTextSize" );
2373 int base_line, cap_line;
2376 const char **faces = icvHersheyGlyphs;
2378 if( !text || !font || !font->ascii || !size )
2379 CV_ERROR( CV_StsNullPtr, "" );
2381 base_line = (font->ascii[0] & 15);
2382 cap_line = (font->ascii[0] >> 4) & 15;
2384 *_base_line = cvRound(base_line*font->vscale);
2385 size->height = cvRound((cap_line + base_line)*font->vscale + font->thickness);
2387 for( i = 0; text[i] != '\0'; i++ )
2389 int c = (uchar)text[i];
2393 if( c > 128 || c < ' ' )
2396 ptr = faces[font->ascii[(c-' ')+1]];
2397 p.x = (unsigned char)ptr[0] - 'R';
2398 p.y = (unsigned char)ptr[1] - 'R';
2399 view_x += (p.y - p.x)*font->hscale;
2402 size->width = cvRound(view_x + font->thickness);
2408 static const CvPoint icvCodeDeltas[8] =
2409 { {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1} };
2411 #define CV_ADJUST_EDGE_COUNT( count, seq ) \
2412 ((count) -= ((count) == (seq)->total && !CV_IS_SEQ_CLOSED(seq)))
2415 cvDrawContours( void* img, CvSeq* contour,
2416 CvScalar externalColor, CvScalar holeColor,
2417 int maxLevel, int thickness,
2418 int line_type, CvPoint offset )
2420 CvSeq *contour0 = contour, *h_next = 0;
2421 CvMemStorage* st = 0;
2423 CvContour* edges = 0;
2425 CvTreeNodeIterator iterator;
2427 CV_FUNCNAME( "cvDrawContours" );
2432 CvMat stub, *mat = (CvMat*)img;
2433 double ext_buf[4], hole_buf[4];
2435 CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
2437 if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
2444 CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
2446 if( thickness < -1 || thickness > 255 )
2447 CV_ERROR( CV_StsOutOfRange, "" );
2449 CV_CALL( cvScalarToRawData( &externalColor, ext_buf, mat->type, 0 ));
2450 CV_CALL( cvScalarToRawData( &holeColor, hole_buf, mat->type, 0 ));
2454 h_next = contour->h_next;
2455 contour->h_next = 0;
2456 maxLevel = -maxLevel+1;
2461 if( contour->storage )
2462 st = cvCreateChildMemStorage( contour->storage );
2464 st = cvCreateMemStorage( CV_DRAWING_STORAGE_BLOCK );
2465 tseq = cvCreateSeq( 0, sizeof(CvContour), sizeof(CvPoint), st );
2466 edges = (CvContour*)cvCreateSeq( 0, sizeof(CvContour), sizeof(CvPolyEdge), st );
2469 memset( &writer, 0, sizeof(writer));
2471 cvInitTreeNodeIterator( &iterator, contour, maxLevel );
2473 while( (contour = (CvSeq*)cvNextTreeNode( &iterator )) != 0 )
2476 int i, count = contour->total;
2477 int elem_type = CV_MAT_TYPE(contour->flags);
2478 void* clr = (contour->flags & CV_SEQ_FLAG_HOLE) == 0 ? ext_buf : hole_buf;
2480 cvStartReadSeq( contour, &reader, 0 );
2482 if( CV_IS_SEQ_CHAIN_CONTOUR( contour ))
2484 CvPoint pt = ((CvChain*)contour)->origin;
2485 CvPoint prev_pt = pt;
2486 char prev_code = reader.ptr ? reader.ptr[0] : '\0';
2491 cvStartAppendToSeq( tseq, &writer );
2492 CV_WRITE_SEQ_ELEM( pt, writer );
2495 prev_pt.x += offset.x;
2496 prev_pt.y += offset.y;
2498 for( i = 0; i < count; i++ )
2501 CV_READ_SEQ_ELEM( code, reader );
2503 assert( (code & ~7) == 0 );
2505 if( code != prev_code )
2508 if( thickness >= 0 )
2510 icvThickLine( mat, prev_pt, pt, clr, thickness, line_type, 2, 0 );
2514 CV_WRITE_SEQ_ELEM( pt, writer );
2519 pt.x += icvCodeDeltas[(int)code].x;
2520 pt.y += icvCodeDeltas[(int)code].y;
2523 if( thickness >= 0 )
2525 icvThickLine( mat, prev_pt, ((CvChain*)contour)->origin,
2526 clr, thickness, line_type, 2, 0 );
2530 CV_WRITE_SEQ_ELEM( pt, writer );
2531 cvEndWriteSeq( &writer );
2532 CV_CALL( icvCollectPolyEdges( mat, tseq, edges, ext_buf, line_type, 0 ));
2535 else if( CV_IS_SEQ_POLYLINE( contour ))
2537 if( thickness >= 0 )
2542 count -= !CV_IS_SEQ_CLOSED(contour);
2543 if( elem_type == CV_32SC2 )
2545 CV_READ_SEQ_ELEM( pt1, reader );
2552 CV_READ_SEQ_ELEM( pt1f, reader );
2553 pt1.x = cvRound( (pt1f.x + offset.x) * XY_ONE );
2554 pt1.y = cvRound( (pt1f.y + offset.y) * XY_ONE );
2558 for( i = 0; i < count; i++ )
2560 if( elem_type == CV_32SC2 )
2562 CV_READ_SEQ_ELEM( pt2, reader );
2569 CV_READ_SEQ_ELEM( pt2f, reader );
2570 pt2.x = cvRound( pt2f.x * XY_ONE );
2571 pt2.y = cvRound( pt2f.y * XY_ONE );
2573 icvThickLine( mat, pt1, pt2, clr, thickness, line_type, 2, shift );
2579 CV_CALL( icvCollectPolyEdges( mat, contour, edges, ext_buf, line_type, 0, offset ));
2586 CV_CALL( icvFillEdgeCollection( mat, edges, ext_buf ));
2591 if( h_next && contour0 )
2592 contour0->h_next = h_next;
2594 cvReleaseMemStorage( &st );