//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.cpp
CV_IMPL void
cvLine( 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 void
ThickLine( 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 void
Line( 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 void
Line2( 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 void
LineAA( 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
}
}//cxcore.h
/* Draws 4-connected, 8-connected