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
This commit is contained in:
Vadim Pisarevsky 2020-02-04 19:37:33 +03:00 committed by GitHub
parent 4e4dfffe06
commit e50acb923e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 93 additions and 112 deletions

View File

@ -308,7 +308,7 @@ LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color )
int nch = img.channels();
uchar* ptr = img.ptr();
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) )
{
@ -316,15 +316,8 @@ LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* 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;
size.width <<= XY_SHIFT;
size.height <<= XY_SHIFT;
if( !clipLine( size, pt1, pt2 ))
return;
@ -403,171 +396,160 @@ LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color )
if( nch == 3 )
{
#define ICV_PUT_POINT() \
#define ICV_PUT_POINT(x, y) \
{ \
uchar* tptr = ptr + (x)*3 + (y)*step; \
_cb = tptr[0]; \
_cb += ((cb - _cb)*a + 127)>> 8;\
_cb += ((cb - _cb)*a + 127)>> 8;\
_cg = tptr[1]; \
_cg += ((cg - _cg)*a + 127)>> 8;\
_cg += ((cg - _cg)*a + 127)>> 8;\
_cr = tptr[2]; \
_cr += ((cr - _cr)*a + 127)>> 8;\
_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;
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 +
(((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();
if( (unsigned)y < (unsigned)size0.height )
ICV_PUT_POINT(x, y)
tptr += step;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
if( (unsigned)(y+1) < (unsigned)size0.height )
ICV_PUT_POINT(x, y+1)
tptr += step;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
pt1.y += y_step;
ptr += 3;
scount++;
ecount--;
if( (unsigned)(y+2) < (unsigned)size0.height )
ICV_PUT_POINT(x, y+2)
}
}
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 +
(((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();
if( (unsigned)x < (unsigned)size0.width )
ICV_PUT_POINT(x, y)
tptr += 3;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
if( (unsigned)(x+1) < (unsigned)size0.width )
ICV_PUT_POINT(x+1, y)
tptr += 3;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
pt1.x += x_step;
ptr += step;
scount++;
ecount--;
if( (unsigned)(x+2) < (unsigned)size0.width )
ICV_PUT_POINT(x+2, y)
}
}
#undef ICV_PUT_POINT
}
else if(nch == 1)
{
#define ICV_PUT_POINT() \
#define ICV_PUT_POINT(x, y) \
{ \
uchar* tptr = ptr + (x) + (y) * step; \
_cb = tptr[0]; \
_cb += ((cb - _cb)*a + 127)>> 8;\
_cb += ((cb - _cb)*a + 127)>> 8;\
tptr[0] = (uchar)_cb; \
}
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 +
(((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();
if( (unsigned)y < (unsigned)size0.height )
ICV_PUT_POINT(x, y)
tptr += step;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
if( (unsigned)(y+1) < (unsigned)size0.height )
ICV_PUT_POINT(x, y+1)
tptr += step;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
pt1.y += y_step;
ptr++;
scount++;
ecount--;
if( (unsigned)(y+2) < (unsigned)size0.height )
ICV_PUT_POINT(x, y+2)
}
}
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 +
(((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();
if( (unsigned)x < (unsigned)size0.width )
ICV_PUT_POINT(x, y)
tptr++;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
if( (unsigned)(x+1) < (unsigned)size0.width )
ICV_PUT_POINT(x+1, y)
tptr++;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
pt1.x += x_step;
ptr += step;
scount++;
ecount--;
if( (unsigned)(x+2) < (unsigned)size0.width )
ICV_PUT_POINT(x+2, y)
}
}
#undef ICV_PUT_POINT
}
else
{
#define ICV_PUT_POINT() \
#define ICV_PUT_POINT(x, y) \
{ \
uchar* tptr = ptr + (x)*4 + (y)*step; \
_cb = tptr[0]; \
_cb += ((cb - _cb)*a + 127)>> 8;\
_cb += ((cb - _cb)*a + 127)>> 8;\
_cg = tptr[1]; \
_cg += ((cg - _cg)*a + 127)>> 8;\
_cg += ((cg - _cg)*a + 127)>> 8;\
_cr = tptr[2]; \
_cr += ((cr - _cr)*a + 127)>> 8;\
_cr += ((cr - _cr)*a + 127)>> 8;\
_ca = tptr[3]; \
_ca += ((ca - _ca)*a + 127)>> 8;\
_ca += ((ca - _ca)*a + 127)>> 8;\
tptr[0] = (uchar)_cb; \
tptr[1] = (uchar)_cg; \
tptr[2] = (uchar)_cr; \
@ -575,66 +557,55 @@ LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color )
}
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 +
(((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();
if( (unsigned)y < (unsigned)size0.height )
ICV_PUT_POINT(x, y)
tptr += step;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
if( (unsigned)(y+1) < (unsigned)size0.height )
ICV_PUT_POINT(x, y+1)
tptr += step;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
pt1.y += y_step;
ptr += 4;
scount++;
ecount--;
if( (unsigned)(y+2) < (unsigned)size0.height )
ICV_PUT_POINT(x, y+2)
}
}
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 +
(((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();
if( (unsigned)x < (unsigned)size0.width )
ICV_PUT_POINT(x, y)
tptr += 4;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
if( (unsigned)(x+1) < (unsigned)size0.width )
ICV_PUT_POINT(x+1, y)
tptr += 4;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
pt1.x += x_step;
ptr += step;
scount++;
ecount--;
if( (unsigned)(x+2) < (unsigned)size0.width )
ICV_PUT_POINT(x+2, y)
}
}
#undef ICV_PUT_POINT

View File

@ -583,4 +583,14 @@ TEST(Drawing, line)
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