Unverified Commit e50acb92 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky Committed by GitHub

Merge pull request #16495 from vpisarev:drawing_aa_border_fix

* fixed antialiased line rendering to process image border correctly

* fixed warning on Windows

* imgproc(test): circle drawing regression
parent 4e4dfffe
...@@ -308,7 +308,7 @@ LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color ) ...@@ -308,7 +308,7 @@ LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color )
int nch = img.channels(); int nch = img.channels();
uchar* ptr = img.ptr(); uchar* ptr = img.ptr();
size_t step = img.step; size_t step = img.step;
Size2l size(img.size()); Size2l size0(img.size()), size = size0;
if( !((nch == 1 || nch == 3 || nch == 4) && img.depth() == CV_8U) ) if( !((nch == 1 || nch == 3 || nch == 4) && img.depth() == CV_8U) )
{ {
...@@ -316,15 +316,8 @@ LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color ) ...@@ -316,15 +316,8 @@ LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color )
return; return;
} }
pt1.x -= XY_ONE*2; size.width <<= XY_SHIFT;
pt1.y -= XY_ONE*2; size.height <<= XY_SHIFT;
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 )) if( !clipLine( size, pt1, pt2 ))
return; return;
...@@ -403,171 +396,160 @@ LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color ) ...@@ -403,171 +396,160 @@ LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color )
if( nch == 3 ) if( nch == 3 )
{ {
#define ICV_PUT_POINT() \ #define ICV_PUT_POINT(x, y) \
{ \ { \
uchar* tptr = ptr + (x)*3 + (y)*step; \
_cb = tptr[0]; \ _cb = tptr[0]; \
_cb += ((cb - _cb)*a + 127)>> 8;\ _cb += ((cb - _cb)*a + 127)>> 8;\
_cb += ((cb - _cb)*a + 127)>> 8;\
_cg = tptr[1]; \ _cg = tptr[1]; \
_cg += ((cg - _cg)*a + 127)>> 8;\ _cg += ((cg - _cg)*a + 127)>> 8;\
_cg += ((cg - _cg)*a + 127)>> 8;\
_cr = tptr[2]; \ _cr = tptr[2]; \
_cr += ((cr - _cr)*a + 127)>> 8;\ _cr += ((cr - _cr)*a + 127)>> 8;\
_cr += ((cr - _cr)*a + 127)>> 8;\
tptr[0] = (uchar)_cb; \ tptr[0] = (uchar)_cb; \
tptr[1] = (uchar)_cg; \ tptr[1] = (uchar)_cg; \
tptr[2] = (uchar)_cr; \ tptr[2] = (uchar)_cr; \
} }
if( ax > ay ) if( ax > ay )
{ {
ptr += (pt1.x >> XY_SHIFT) * 3; int x = (int)(pt1.x >> XY_SHIFT);
while( ecount >= 0 ) for( ; ecount >= 0; x++, pt1.y += y_step, scount++, ecount-- )
{ {
uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step; if( (unsigned)x >= (unsigned)size0.width )
continue;
int y = (int)((pt1.y >> XY_SHIFT) - 1);
int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 + int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
(((ecount >= 2) + 1) & (ecount | 2))]; (((ecount >= 2) + 1) & (ecount | 2))];
int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31; int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff; a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)y < (unsigned)size0.height )
ICV_PUT_POINT(); ICV_PUT_POINT(x, y)
tptr += step;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff; a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)(y+1) < (unsigned)size0.height )
ICV_PUT_POINT(); ICV_PUT_POINT(x, y+1)
tptr += step;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff; a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)(y+2) < (unsigned)size0.height )
ICV_PUT_POINT(); ICV_PUT_POINT(x, y+2)
pt1.y += y_step;
ptr += 3;
scount++;
ecount--;
} }
} }
else else
{ {
ptr += (pt1.y >> XY_SHIFT) * step; int y = (int)(pt1.y >> XY_SHIFT);
while( ecount >= 0 ) for( ; ecount >= 0; y++, pt1.x += x_step, scount++, ecount-- )
{ {
uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1) * 3; if( (unsigned)y >= (unsigned)size0.height )
continue;
int x = (int)((pt1.x >> XY_SHIFT) - 1);
int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 + int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
(((ecount >= 2) + 1) & (ecount | 2))]; (((ecount >= 2) + 1) & (ecount | 2))];
int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31; int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff; a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)x < (unsigned)size0.width )
ICV_PUT_POINT(); ICV_PUT_POINT(x, y)
tptr += 3;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff; a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)(x+1) < (unsigned)size0.width )
ICV_PUT_POINT(); ICV_PUT_POINT(x+1, y)
tptr += 3;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff; a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)(x+2) < (unsigned)size0.width )
ICV_PUT_POINT(); ICV_PUT_POINT(x+2, y)
pt1.x += x_step;
ptr += step;
scount++;
ecount--;
} }
} }
#undef ICV_PUT_POINT #undef ICV_PUT_POINT
} }
else if(nch == 1) else if(nch == 1)
{ {
#define ICV_PUT_POINT() \ #define ICV_PUT_POINT(x, y) \
{ \ { \
uchar* tptr = ptr + (x) + (y) * step; \
_cb = tptr[0]; \ _cb = tptr[0]; \
_cb += ((cb - _cb)*a + 127)>> 8;\ _cb += ((cb - _cb)*a + 127)>> 8;\
_cb += ((cb - _cb)*a + 127)>> 8;\
tptr[0] = (uchar)_cb; \ tptr[0] = (uchar)_cb; \
} }
if( ax > ay ) if( ax > ay )
{ {
ptr += (pt1.x >> XY_SHIFT); int x = (int)(pt1.x >> XY_SHIFT);
while( ecount >= 0 ) for( ; ecount >= 0; x++, pt1.y += y_step, scount++, ecount-- )
{ {
uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step; if( (unsigned)x >= (unsigned)size0.width )
continue;
int y = (int)((pt1.y >> XY_SHIFT) - 1);
int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 + int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
(((ecount >= 2) + 1) & (ecount | 2))]; (((ecount >= 2) + 1) & (ecount | 2))];
int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31; int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff; a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)y < (unsigned)size0.height )
ICV_PUT_POINT(); ICV_PUT_POINT(x, y)
tptr += step;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff; a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)(y+1) < (unsigned)size0.height )
ICV_PUT_POINT(); ICV_PUT_POINT(x, y+1)
tptr += step;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff; a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)(y+2) < (unsigned)size0.height )
ICV_PUT_POINT(); ICV_PUT_POINT(x, y+2)
pt1.y += y_step;
ptr++;
scount++;
ecount--;
} }
} }
else else
{ {
ptr += (pt1.y >> XY_SHIFT) * step; int y = (int)(pt1.y >> XY_SHIFT);
while( ecount >= 0 ) for( ; ecount >= 0; y++, pt1.x += x_step, scount++, ecount-- )
{ {
uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1); if( (unsigned)y >= (unsigned)size0.height )
continue;
int x = (int)((pt1.x >> XY_SHIFT) - 1);
int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 + int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
(((ecount >= 2) + 1) & (ecount | 2))]; (((ecount >= 2) + 1) & (ecount | 2))];
int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31; int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff; a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)x < (unsigned)size0.width )
ICV_PUT_POINT(); ICV_PUT_POINT(x, y)
tptr++;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff; a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)(x+1) < (unsigned)size0.width )
ICV_PUT_POINT(); ICV_PUT_POINT(x+1, y)
tptr++;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff; a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)(x+2) < (unsigned)size0.width )
ICV_PUT_POINT(); ICV_PUT_POINT(x+2, y)
pt1.x += x_step;
ptr += step;
scount++;
ecount--;
} }
} }
#undef ICV_PUT_POINT #undef ICV_PUT_POINT
} }
else else
{ {
#define ICV_PUT_POINT() \ #define ICV_PUT_POINT(x, y) \
{ \ { \
uchar* tptr = ptr + (x)*4 + (y)*step; \
_cb = tptr[0]; \ _cb = tptr[0]; \
_cb += ((cb - _cb)*a + 127)>> 8;\ _cb += ((cb - _cb)*a + 127)>> 8;\
_cb += ((cb - _cb)*a + 127)>> 8;\
_cg = tptr[1]; \ _cg = tptr[1]; \
_cg += ((cg - _cg)*a + 127)>> 8;\ _cg += ((cg - _cg)*a + 127)>> 8;\
_cg += ((cg - _cg)*a + 127)>> 8;\
_cr = tptr[2]; \ _cr = tptr[2]; \
_cr += ((cr - _cr)*a + 127)>> 8;\ _cr += ((cr - _cr)*a + 127)>> 8;\
_cr += ((cr - _cr)*a + 127)>> 8;\
_ca = tptr[3]; \ _ca = tptr[3]; \
_ca += ((ca - _ca)*a + 127)>> 8;\ _ca += ((ca - _ca)*a + 127)>> 8;\
_ca += ((ca - _ca)*a + 127)>> 8;\
tptr[0] = (uchar)_cb; \ tptr[0] = (uchar)_cb; \
tptr[1] = (uchar)_cg; \ tptr[1] = (uchar)_cg; \
tptr[2] = (uchar)_cr; \ tptr[2] = (uchar)_cr; \
...@@ -575,66 +557,55 @@ LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color ) ...@@ -575,66 +557,55 @@ LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color )
} }
if( ax > ay ) if( ax > ay )
{ {
ptr += (pt1.x >> XY_SHIFT) * 4; int x = (int)(pt1.x >> XY_SHIFT);
while( ecount >= 0 ) for( ; ecount >= 0; x++, pt1.y += y_step, scount++, ecount-- )
{ {
uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step; if( (unsigned)x >= (unsigned)size0.width )
continue;
int y = (int)((pt1.y >> XY_SHIFT) - 1);
int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 + int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
(((ecount >= 2) + 1) & (ecount | 2))]; (((ecount >= 2) + 1) & (ecount | 2))];
int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31; int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff; a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)y < (unsigned)size0.height )
ICV_PUT_POINT(); ICV_PUT_POINT(x, y)
tptr += step;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff; a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)(y+1) < (unsigned)size0.height )
ICV_PUT_POINT(); ICV_PUT_POINT(x, y+1)
tptr += step;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff; a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)(y+2) < (unsigned)size0.height )
ICV_PUT_POINT(); ICV_PUT_POINT(x, y+2)
pt1.y += y_step;
ptr += 4;
scount++;
ecount--;
} }
} }
else else
{ {
ptr += (pt1.y >> XY_SHIFT) * step; int y = (int)(pt1.y >> XY_SHIFT);
while( ecount >= 0 ) for( ; ecount >= 0; y++, pt1.x += x_step, scount++, ecount-- )
{ {
uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1) * 4; if( (unsigned)y >= (unsigned)size0.height )
continue;
int x = (int)((pt1.x >> XY_SHIFT) - 1);
int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 + int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
(((ecount >= 2) + 1) & (ecount | 2))]; (((ecount >= 2) + 1) & (ecount | 2))];
int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31; int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff; a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)x < (unsigned)size0.width )
ICV_PUT_POINT(); ICV_PUT_POINT(x, y)
tptr += 4;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff; a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)(x+1) < (unsigned)size0.width )
ICV_PUT_POINT(); ICV_PUT_POINT(x+1, y)
tptr += 4;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff; a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT(); if( (unsigned)(x+2) < (unsigned)size0.width )
ICV_PUT_POINT(); ICV_PUT_POINT(x+2, y)
pt1.x += x_step;
ptr += step;
scount++;
ecount--;
} }
} }
#undef ICV_PUT_POINT #undef ICV_PUT_POINT
......
...@@ -583,4 +583,14 @@ TEST(Drawing, line) ...@@ -583,4 +583,14 @@ TEST(Drawing, line)
ASSERT_THROW(line(mat, Point(1,1),Point(99,99),Scalar(255),0), cv::Exception); ASSERT_THROW(line(mat, Point(1,1),Point(99,99),Scalar(255),0), cv::Exception);
} }
TEST(Drawing, regression_16308)
{
Mat_<uchar> img(Size(100, 100), (uchar)0);
circle(img, Point(50, 50), 50, 255, 1, LINE_AA);
EXPECT_NE(0, (int)img.at<uchar>(0, 50));
EXPECT_NE(0, (int)img.at<uchar>(50, 0));
EXPECT_NE(0, (int)img.at<uchar>(50, 99));
EXPECT_NE(0, (int)img.at<uchar>(99, 50));
}
}} // namespace }} // namespace
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment