diff --git a/modules/core/src/drawing.cpp b/modules/core/src/drawing.cpp index 3d1dc3a994bf0c186ad72e624c5f53a24aecd603..9016d0f302e686feb0a48f5f97b898e94c35d760 100644 --- a/modules/core/src/drawing.cpp +++ b/modules/core/src/drawing.cpp @@ -552,7 +552,7 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) int dx, dy; int ecount; int ax, ay; - int i, j; + int i, j, x, y; int x_step, y_step; int cb = ((uchar*)color)[0]; int cg = ((uchar*)color)[1]; @@ -560,20 +560,11 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) int pix_size = (int)img.elemSize(); uchar *ptr = img.data, *tptr; size_t step = img.step; - Size size = img.size(); + Size size = img.size(), sizeScaled(size.width*XY_ONE, size.height*XY_ONE); //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 )) + if( !clipLine( sizeScaled, pt1, pt2 )) return; dx = pt2.x - pt1.x; @@ -620,40 +611,41 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) if( pix_size == 3 ) { - #define ICV_PUT_POINT() \ - { \ - tptr[0] = (uchar)cb; \ - tptr[1] = (uchar)cg; \ - tptr[2] = (uchar)cr; \ + #define ICV_PUT_POINT(_x,_y) \ + x = (_x); y = (_y); \ + if( 0 <= x && x < size.width && \ + 0 <= y && y < size.height ) \ + { \ + tptr = ptr + y*step + x*3; \ + 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(); + ICV_PUT_POINT((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT, + (pt2.y + (XY_ONE >> 1)) >> XY_SHIFT); if( ax > ay ) { - ptr += (pt1.x >> XY_SHIFT) * 3; + pt1.x >>= XY_SHIFT; while( ecount >= 0 ) { - tptr = ptr + (pt1.y >> XY_SHIFT) * step; - ICV_PUT_POINT(); + ICV_PUT_POINT(pt1.x, pt1.y >> XY_SHIFT); + pt1.x++; pt1.y += y_step; - ptr += 3; ecount--; } } else { - ptr += (pt1.y >> XY_SHIFT) * step; - + pt1.y >>= XY_SHIFT; + while( ecount >= 0 ) { - tptr = ptr + (pt1.x >> XY_SHIFT) * 3; - ICV_PUT_POINT(); + ICV_PUT_POINT(pt1.x >> XY_SHIFT, pt1.y); pt1.x += x_step; - ptr += step; + pt1.y++; ecount--; } } @@ -662,80 +654,85 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) } else if( pix_size == 1 ) { - #define ICV_PUT_POINT() \ - { \ - tptr[0] = (uchar)cb; \ + #define ICV_PUT_POINT(_x,_y) \ + x = (_x); y = (_y); \ + if( 0 <= x && x < size.width && \ + 0 <= y && y < size.height ) \ + { \ + tptr = ptr + y*step + x;\ + tptr[0] = (uchar)cb; \ } - tptr = ptr + ((pt2.x + (XY_ONE >> 1))>> XY_SHIFT) + - ((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)*step; - ICV_PUT_POINT(); - + ICV_PUT_POINT((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT, + (pt2.y + (XY_ONE >> 1)) >> XY_SHIFT); + if( ax > ay ) { - ptr += (pt1.x >> XY_SHIFT); + pt1.x >>= XY_SHIFT; while( ecount >= 0 ) { - tptr = ptr + (pt1.y >> XY_SHIFT) * step; - ICV_PUT_POINT(); + ICV_PUT_POINT(pt1.x, pt1.y >> XY_SHIFT); + pt1.x++; pt1.y += y_step; - ptr++; ecount--; } } else { - ptr += (pt1.y >> XY_SHIFT) * step; - + pt1.y >>= XY_SHIFT; + while( ecount >= 0 ) { - tptr = ptr + (pt1.x >> XY_SHIFT); - ICV_PUT_POINT(); + ICV_PUT_POINT(pt1.x >> XY_SHIFT, pt1.y); pt1.x += x_step; - ptr += step; + pt1.y++; ecount--; } } + #undef ICV_PUT_POINT } else { - #define ICV_PUT_POINT() \ - for( j = 0; j < pix_size; j++ ) \ - tptr[j] = ((uchar*)color)[j]; + #define ICV_PUT_POINT(_x,_y) \ + x = (_x); y = (_y); \ + if( 0 <= x && x < size.width && \ + 0 <= y && y < size.height ) \ + { \ + tptr = ptr + y*step + x*pix_size;\ + 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(); - + ICV_PUT_POINT((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT, + (pt2.y + (XY_ONE >> 1)) >> XY_SHIFT); + if( ax > ay ) { - ptr += (pt1.x >> XY_SHIFT) * pix_size; - + pt1.x >>= XY_SHIFT; + while( ecount >= 0 ) { - tptr = ptr + (pt1.y >> XY_SHIFT) * step; - ICV_PUT_POINT(); + ICV_PUT_POINT(pt1.x, pt1.y >> XY_SHIFT); + pt1.x++; pt1.y += y_step; - ptr += pix_size; ecount--; } } else { - ptr += (pt1.y >> XY_SHIFT) * step; - + pt1.y >>= XY_SHIFT; + while( ecount >= 0 ) { - tptr = ptr + (pt1.x >> XY_SHIFT) * pix_size; - ICV_PUT_POINT(); + ICV_PUT_POINT(pt1.x >> XY_SHIFT, pt1.y); pt1.x += x_step; - ptr += step; + pt1.y++; ecount--; } } - + #undef ICV_PUT_POINT } } @@ -1013,7 +1010,7 @@ FillConvexPoly( Mat& img, const Point* v, int npts, const void* color, int line_ LineAA( img, p0, p, color ); p0 = p; } - + xmin = (xmin + delta) >> shift; xmax = (xmax + delta) >> shift; ymin = (ymin + delta) >> shift; diff --git a/modules/highgui/test/test_drawing.cpp b/modules/highgui/test/test_drawing.cpp index 52ece4072ae3b1e8c8466e6d7382610c401447fe..a887c0f746d435d29dc4c76171aebea3eb6913f0 100644 --- a/modules/highgui/test/test_drawing.cpp +++ b/modules/highgui/test/test_drawing.cpp @@ -408,3 +408,37 @@ int CV_DrawingTest_C::checkLineIterator( Mat& _img ) TEST(Highgui_Drawing_CPP, regression) { CV_DrawingTest_CPP test; test.safe_run(); } TEST(Highgui_Drawing_C, regression) { CV_DrawingTest_C test; test.safe_run(); } + +class CV_FillConvexPolyTest : public cvtest::BaseTest +{ +public: + CV_FillConvexPolyTest() {} + ~CV_FillConvexPolyTest() {} +protected: + void run(int) + { + vector line1; + vector line2; + + line1.push_back(Point(1, 1)); + line1.push_back(Point(5, 1)); + line1.push_back(Point(5, 8)); + line1.push_back(Point(1, 8)); + + line2.push_back(Point(2, 2)); + line2.push_back(Point(10, 2)); + line2.push_back(Point(10, 16)); + line2.push_back(Point(2, 16)); + + Mat gray0(10,10,CV_8U, Scalar(0)); + fillConvexPoly(gray0, line1, Scalar(255), 8, 0); + int nz1 = countNonZero(gray0); + + fillConvexPoly(gray0, line2, Scalar(0), 8, 1); + int nz2 = countNonZero(gray0)/255; + + CV_Assert( nz1 == 40 && nz2 == 0 ); + } +}; + +TEST(Highgui_Drawing_FillConvexPoly, clipping) { CV_FillConvexPolyTest test; test.safe_run(); }