//cxcore.h/* Draws 4-connected, 8-connected or antialiased line segment connecting two points */CVAPI(void) cvLine( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color, int thickness CV_DEFAULT(1), int line_type CV_DEFAULT(8), int shift CV_DEFAULT(0) );//cxDrawing.cppCV_IMPL voidcvLine( CvArr* _img, CvPoint pt1, CvPoint pt2, CvScalar color, int thickness, int line_type, int shift ){ cv::Mat img = cv::cvarrToMat(_img); cv::line( img, pt1, pt2, color, thickness, line_type, shift );}//cxDrawing.cpp/****************************************************************************************\* External functions *\****************************************************************************************/void line( Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness, int line_type, int shift ){ if( line_type == CV_AA && img.depth() != CV_8U ) line_type = 8; CV_Assert( 0 <= thickness && thickness <= 255 ); CV_Assert( 0 <= shift && shift <= XY_SHIFT ); double buf[4]; scalarToRawData( color, buf, img.type(), 0 ); ThickLine( img, pt1, pt2, buf, thickness, line_type, 3, shift ); }static inline void scalarToRawData(const Scalar& s, void* buf, int type, int unroll_to=0){ int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); switch(depth) { case CV_8U: s.convertTo((uchar*)buf, cn, unroll_to); break; case CV_8S: s.convertTo((schar*)buf, cn, unroll_to); break; case CV_16U: s.convertTo((ushort*)buf, cn, unroll_to); break; case CV_16S: s.convertTo((short*)buf, cn, unroll_to); break; case CV_32S: s.convertTo((int*)buf, cn, unroll_to); break; case CV_32F: s.convertTo((float*)buf, cn, unroll_to); break; case CV_64F: s.convertTo((double*)buf, cn, unroll_to); break; default: CV_Error(CV_StsUnsupportedFormat,""); }}static voidThickLine( Mat& img, Point p0, Point p1, const void* color, int thickness, int line_type, int flags, int shift ){ static const double INV_XY_ONE = 1./XY_ONE; p0.x <<= XY_SHIFT - shift; p0.y <<= XY_SHIFT - shift; p1.x <<= XY_SHIFT - shift; p1.y <<= XY_SHIFT - shift; if( thickness <= 1 ) { if( line_type < CV_AA ) { if( line_type == 1 || line_type == 4 || shift == 0 ) { p0.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT; p0.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT; p1.x = (p1.x + (XY_ONE>>1)) >> XY_SHIFT; p1.y = (p1.y + (XY_ONE>>1)) >> XY_SHIFT; Line( img, p0, p1, color, line_type ); } else Line2( img, p0, p1, color ); } else LineAA( img, p0, p1, color ); } else { Point pt[4], dp = Point(0,0); double dx = (p0.x - p1.x)*INV_XY_ONE, dy = (p1.y - p0.y)*INV_XY_ONE; double r = dx * dx + dy * dy; int i, oddThickness = thickness & 1; thickness <<= XY_SHIFT - 1; if( fabs(r) > DBL_EPSILON ) { r = (thickness + oddThickness*XY_ONE*0.5)/std::sqrt(r); dp.x = cvRound( dy * r ); dp.y = cvRound( dx * r ); pt[0].x = p0.x + dp.x; pt[0].y = p0.y + dp.y; pt[1].x = p0.x - dp.x; pt[1].y = p0.y - dp.y; pt[2].x = p1.x - dp.x; pt[2].y = p1.y - dp.y; pt[3].x = p1.x + dp.x; pt[3].y = p1.y + dp.y; FillConvexPoly( img, pt, 4, color, line_type, XY_SHIFT ); } for( i = 0; i < 2; i++ ) { if( flags & (i+1) ) { if( line_type < CV_AA ) { Point center; center.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT; center.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT; Circle( img, center, (thickness + (XY_ONE>>1)) >> XY_SHIFT, color, 1 ); } else { EllipseEx( img, p0, cvSize(thickness, thickness), 0, 0, 360, color, -1, line_type ); } } p0 = p1; } }}static voidLine( Mat& img, Point pt1, Point pt2, const void* color, int connectivity = 8 ){ if( connectivity == 0 ) connectivity = 8; if( connectivity == 1 ) connectivity = 4; LineIterator iterator(img, pt1, pt2, connectivity, true); int i, count = iterator.count; int pix_size = (int)img.elemSize(); for( i = 0; i < count; i++, ++iterator ) { CV_MEMCPY_AUTO( *iterator, color, pix_size ); }}static voidLine2( Mat& img, Point pt1, Point pt2, const void* color ){ int dx, dy; int ecount; int ax, ay; int i, j; int x_step, y_step; int cb = ((uchar*)color)[0]; int cg = ((uchar*)color)[1]; int cr = ((uchar*)color)[2]; int pix_size = (int)img.elemSize(); uchar *ptr = img.data, *tptr; size_t step = img.step; Size size = img.size(); //assert( img && (nch == 1 || nch == 3) && img.depth() == CV_8U ); pt1.x -= XY_ONE*2; pt1.y -= XY_ONE*2; pt2.x -= XY_ONE*2; pt2.y -= XY_ONE*2; ptr += img.step*2 + 2*pix_size; size.width = ((size.width - 5) << XY_SHIFT) + 1; size.height = ((size.height - 5) << XY_SHIFT) + 1; if( !clipLine( size, pt1, pt2 )) return; dx = pt2.x - pt1.x; dy = pt2.y - pt1.y; j = dx < 0 ? -1 : 0; ax = (dx ^ j) - j; i = dy < 0 ? -1 : 0; ay = (dy ^ i) - i; if( ax > ay ) { dx = ax; dy = (dy ^ j) - j; pt1.x ^= pt2.x & j; pt2.x ^= pt1.x & j; pt1.x ^= pt2.x & j; pt1.y ^= pt2.y & j; pt2.y ^= pt1.y & j; pt1.y ^= pt2.y & j; x_step = XY_ONE; y_step = (int) (((int64) dy << XY_SHIFT) / (ax | 1)); ecount = (pt2.x - pt1.x) >> XY_SHIFT; } else { dy = ay; dx = (dx ^ i) - i; pt1.x ^= pt2.x & i; pt2.x ^= pt1.x & i; pt1.x ^= pt2.x & i; pt1.y ^= pt2.y & i; pt2.y ^= pt1.y & i; pt1.y ^= pt2.y & i; x_step = (int) (((int64) dx << XY_SHIFT) / (ay | 1)); y_step = XY_ONE; ecount = (pt2.y - pt1.y) >> XY_SHIFT; } pt1.x += (XY_ONE >> 1); pt1.y += (XY_ONE >> 1); if( pix_size == 3 ) { #define ICV_PUT_POINT() \ { \ tptr[0] = (uchar)cb; \ tptr[1] = (uchar)cg; \ tptr[2] = (uchar)cr; \ } tptr = ptr + ((pt2.x + (XY_ONE >> 1))>> XY_SHIFT)*3 + ((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)*step; ICV_PUT_POINT(); if( ax > ay ) { ptr += (pt1.x >> XY_SHIFT) * 3; while( ecount >= 0 ) { tptr = ptr + (pt1.y >> XY_SHIFT) * step; ICV_PUT_POINT(); pt1.y += y_step; ptr += 3; ecount--; } } else { ptr += (pt1.y >> XY_SHIFT) * step; while( ecount >= 0 ) { tptr = ptr + (pt1.x >> XY_SHIFT) * 3; ICV_PUT_POINT(); pt1.x += x_step; ptr += step; ecount--; } } #undef ICV_PUT_POINT } else if( pix_size == 1 ) { #define ICV_PUT_POINT() \ { \ tptr[0] = (uchar)cb; \ } tptr = ptr + ((pt2.x + (XY_ONE >> 1))>> XY_SHIFT) + ((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)*step; ICV_PUT_POINT(); if( ax > ay ) { ptr += (pt1.x >> XY_SHIFT); while( ecount >= 0 ) { tptr = ptr + (pt1.y >> XY_SHIFT) * step; ICV_PUT_POINT(); pt1.y += y_step; ptr++; ecount--; } } else { ptr += (pt1.y >> XY_SHIFT) * step; while( ecount >= 0 ) { tptr = ptr + (pt1.x >> XY_SHIFT); ICV_PUT_POINT(); pt1.x += x_step; ptr += step; ecount--; } } #undef ICV_PUT_POINT } else { #define ICV_PUT_POINT() \ for( j = 0; j < pix_size; j++ ) \ tptr[j] = ((uchar*)color)[j]; tptr = ptr + ((pt2.x + (XY_ONE >> 1))>> XY_SHIFT)*pix_size + ((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)*step; ICV_PUT_POINT(); if( ax > ay ) { ptr += (pt1.x >> XY_SHIFT) * pix_size; while( ecount >= 0 ) { tptr = ptr + (pt1.y >> XY_SHIFT) * step; ICV_PUT_POINT(); pt1.y += y_step; ptr += pix_size; ecount--; } } else { ptr += (pt1.y >> XY_SHIFT) * step; while( ecount >= 0 ) { tptr = ptr + (pt1.x >> XY_SHIFT) * pix_size; ICV_PUT_POINT(); pt1.x += x_step; ptr += step; ecount--; } } #undef ICV_PUT_POINT }}static voidLineAA( Mat& img, Point pt1, Point pt2, const void* color ){ int dx, dy; int ecount, scount = 0; int slope; int ax, ay; int x_step, y_step; int i, j; int ep_table[9]; int cb = ((uchar*)color)[0], cg = ((uchar*)color)[1], cr = ((uchar*)color)[2]; int _cb, _cg, _cr; int nch = img.channels(); uchar* ptr = img.data; size_t step = img.step; Size size = img.size(); if( !((nch == 1 || nch == 3) && img.depth() == CV_8U) ) { Line(img, pt1, pt2, color); return; } pt1.x -= XY_ONE*2; pt1.y -= XY_ONE*2; pt2.x -= XY_ONE*2; pt2.y -= XY_ONE*2; ptr += img.step*2 + 2*nch; size.width = ((size.width - 5) << XY_SHIFT) + 1; size.height = ((size.height - 5) << XY_SHIFT) + 1; if( !clipLine( size, pt1, pt2 )) return; dx = pt2.x - pt1.x; dy = pt2.y - pt1.y; j = dx < 0 ? -1 : 0; ax = (dx ^ j) - j; i = dy < 0 ? -1 : 0; ay = (dy ^ i) - i; if( ax > ay ) { dx = ax; dy = (dy ^ j) - j; pt1.x ^= pt2.x & j; pt2.x ^= pt1.x & j; pt1.x ^= pt2.x & j; pt1.y ^= pt2.y & j; pt2.y ^= pt1.y & j; pt1.y ^= pt2.y & j; x_step = XY_ONE; y_step = (int) (((int64) dy << XY_SHIFT) / (ax | 1)); pt2.x += XY_ONE; ecount = (pt2.x >> XY_SHIFT) - (pt1.x >> XY_SHIFT); j = -(pt1.x & (XY_ONE - 1)); pt1.y += (int) ((((int64) y_step) * j) >> XY_SHIFT) + (XY_ONE >> 1); slope = (y_step >> (XY_SHIFT - 5)) & 0x3f; slope ^= (y_step < 0 ? 0x3f : 0); /* Get 4-bit fractions for end-point adjustments */ i = (pt1.x >> (XY_SHIFT - 7)) & 0x78; j = (pt2.x >> (XY_SHIFT - 7)) & 0x78; } else { dy = ay; dx = (dx ^ i) - i; pt1.x ^= pt2.x & i; pt2.x ^= pt1.x & i; pt1.x ^= pt2.x & i; pt1.y ^= pt2.y & i; pt2.y ^= pt1.y & i; pt1.y ^= pt2.y & i; x_step = (int) (((int64) dx << XY_SHIFT) / (ay | 1)); y_step = XY_ONE; pt2.y += XY_ONE; ecount = (pt2.y >> XY_SHIFT) - (pt1.y >> XY_SHIFT); j = -(pt1.y & (XY_ONE - 1)); pt1.x += (int) ((((int64) x_step) * j) >> XY_SHIFT) + (XY_ONE >> 1); slope = (x_step >> (XY_SHIFT - 5)) & 0x3f; slope ^= (x_step < 0 ? 0x3f : 0); /* Get 4-bit fractions for end-point adjustments */ i = (pt1.y >> (XY_SHIFT - 7)) & 0x78; j = (pt2.y >> (XY_SHIFT - 7)) & 0x78; } slope = (slope & 0x20) ? 0x100 : SlopeCorrTable[slope]; /* Calc end point correction table */ { int t0 = slope << 7; int t1 = ((0x78 - i) | 4) * slope; int t2 = (j | 4) * slope; ep_table[0] = 0; ep_table[8] = slope; ep_table[1] = ep_table[3] = ((((j - i) & 0x78) | 4) * slope >> 8) & 0x1ff; ep_table[2] = (t1 >> 8) & 0x1ff; ep_table[4] = ((((j - i) + 0x80) | 4) * slope >> 8) & 0x1ff; ep_table[5] = ((t1 + t0) >> 8) & 0x1ff; ep_table[6] = (t2 >> 8) & 0x1ff; ep_table[7] = ((t2 + t0) >> 8) & 0x1ff; } if( nch == 3 ) { #define ICV_PUT_POINT() \ { \ _cb = tptr[0]; \ _cb += ((cb - _cb)*a + 127)>> 8;\ _cg = tptr[1]; \ _cg += ((cg - _cg)*a + 127)>> 8;\ _cr = tptr[2]; \ _cr += ((cr - _cr)*a + 127)>> 8;\ tptr[0] = (uchar)_cb; \ tptr[1] = (uchar)_cg; \ tptr[2] = (uchar)_cr; \ } if( ax > ay ) { ptr += (pt1.x >> XY_SHIFT) * 3; while( ecount >= 0 ) { uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step; int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 + (((ecount >= 2) + 1) & (ecount | 2))]; int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31; a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); tptr += step; a = (ep_corr * FilterTable[dist] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); tptr += step; a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); pt1.y += y_step; ptr += 3; scount++; ecount--; } } else { ptr += (pt1.y >> XY_SHIFT) * step; while( ecount >= 0 ) { uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1) * 3; int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 + (((ecount >= 2) + 1) & (ecount | 2))]; int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31; a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); tptr += 3; a = (ep_corr * FilterTable[dist] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); tptr += 3; a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); pt1.x += x_step; ptr += step; scount++; ecount--; } } #undef ICV_PUT_POINT } else { #define ICV_PUT_POINT() \ { \ _cb = tptr[0]; \ _cb += ((cb - _cb)*a + 127)>> 8;\ tptr[0] = (uchar)_cb; \ } if( ax > ay ) { ptr += (pt1.x >> XY_SHIFT); while( ecount >= 0 ) { uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step; int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 + (((ecount >= 2) + 1) & (ecount | 2))]; int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31; a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); tptr += step; a = (ep_corr * FilterTable[dist] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); tptr += step; a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); pt1.y += y_step; ptr++; scount++; ecount--; } } else { ptr += (pt1.y >> XY_SHIFT) * step; while( ecount >= 0 ) { uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1); int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 + (((ecount >= 2) + 1) & (ecount | 2))]; int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31; a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); tptr++; a = (ep_corr * FilterTable[dist] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); tptr++; a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); pt1.x += x_step; ptr += step; scount++; ecount--; } } #undef ICV_PUT_POINT }}