diff --git a/modules/core/include/opencv2/core/core.hpp b/modules/core/include/opencv2/core/core.hpp index 0e8091a54d..6bb295f5c7 100644 --- a/modules/core/include/opencv2/core/core.hpp +++ b/modules/core/include/opencv2/core/core.hpp @@ -407,7 +407,7 @@ public: The class is specialized for each fundamental numerical data type supported by OpenCV. It provides DataDepth::value constant. */ -template class DataDepth {}; +template class DataDepth { public: enum { value = -1, fmt = 0 }; }; template<> class DataDepth { public: enum { value = CV_8U, fmt=(int)'u' }; }; template<> class DataDepth { public: enum { value = CV_8U, fmt=(int)'u' }; }; @@ -880,8 +880,10 @@ public: typedef Point_ Point2i; +typedef Point_ Point2l; typedef Point2i Point; typedef Size_ Size2i; +typedef Size_ Size2l; typedef Size_ Size2d; typedef Size2i Size; typedef Rect_ Rect; @@ -2711,6 +2713,7 @@ CV_EXPORTS_W void polylines(InputOutputArray img, InputArrayOfArrays pts, //! clips the line segment by the rectangle Rect(0, 0, imgSize.width, imgSize.height) CV_EXPORTS bool clipLine(Size imgSize, CV_IN_OUT Point& pt1, CV_IN_OUT Point& pt2); +CV_EXPORTS bool clipLine(Size2l imgSize, CV_IN_OUT Point2l& pt1, CV_IN_OUT Point2l& pt2); //! clips the line segment by the rectangle imgRect CV_EXPORTS_W bool clipLine(Rect imgRect, CV_OUT CV_IN_OUT Point& pt1, CV_OUT CV_IN_OUT Point& pt2); @@ -2748,6 +2751,9 @@ public: CV_EXPORTS_W void ellipse2Poly( Point center, Size axes, int angle, int arcStart, int arcEnd, int delta, CV_OUT vector& pts ); +CV_EXPORTS void ellipse2Poly( Point2d center, Size2d axes, int angle, + int arcStart, int arcEnd, int delta, + CV_OUT vector& pts ); enum { diff --git a/modules/core/src/drawing.cpp b/modules/core/src/drawing.cpp index 5c712ad16e..d0b6fb13b1 100644 --- a/modules/core/src/drawing.cpp +++ b/modules/core/src/drawing.cpp @@ -51,12 +51,12 @@ struct PolyEdge //PolyEdge(int _y0, int _y1, int _x, int _dx) : y0(_y0), y1(_y1), x(_x), dx(_dx) {} int y0, y1; - int x, dx; + int64 x, dx; PolyEdge *next; }; static void -CollectPolyEdges( Mat& img, const Point* v, int npts, +CollectPolyEdges( Mat& img, const Point2l* v, int npts, vector& edges, const void* color, int line_type, int shift, Point offset=Point() ); @@ -64,11 +64,11 @@ static void FillEdgeCollection( Mat& img, vector& edges, const void* color ); static void -PolyLine( Mat& img, const Point* v, int npts, bool closed, +PolyLine( Mat& img, const Point2l* v, int npts, bool closed, const void* color, int thickness, int line_type, int shift ); static void -FillConvexPoly( Mat& img, const Point* v, int npts, +FillConvexPoly( Mat& img, const Point2l* v, int npts, const void* color, int line_type, int shift ); /****************************************************************************************\ @@ -77,14 +77,25 @@ FillConvexPoly( Mat& img, const Point* v, int npts, bool clipLine( Size img_size, Point& pt1, Point& pt2 ) { - int64 x1, y1, x2, y2; + Point2l p1(pt1.x, pt1.y); + Point2l p2(pt2.x, pt2.y); + bool inside = clipLine(Size2l(img_size.width, img_size.height), p1, p2); + pt1.x = (int)p1.x; + pt1.y = (int)p1.y; + pt2.x = (int)p2.x; + pt2.y = (int)p2.y; + return inside; +} + +bool clipLine( Size2l img_size, Point2l& pt1, Point2l& pt2 ) +{ int c1, c2; int64 right = img_size.width-1, bottom = img_size.height-1; if( img_size.width <= 0 || img_size.height <= 0 ) return false; - x1 = pt1.x; y1 = pt1.y; x2 = pt2.x; y2 = pt2.y; + int64 &x1 = pt1.x, &y1 = pt1.y, &x2 = pt2.x, &y2 = pt2.y; c1 = (x1 < 0) + (x1 > right) * 2 + (y1 < 0) * 4 + (y1 > bottom) * 8; c2 = (x2 < 0) + (x2 > right) * 2 + (y2 < 0) * 4 + (y2 > bottom) * 8; @@ -124,11 +135,6 @@ bool clipLine( Size img_size, Point& pt1, Point& pt2 ) } assert( (c1 & c2) != 0 || (x1 | y1 | x2 | y2) >= 0 ); - - pt1.x = (int)x1; - pt1.y = (int)y1; - pt2.x = (int)x2; - pt2.y = (int)y2; } return (c1 | c2) == 0; @@ -279,25 +285,25 @@ static const int FilterTable[] = { }; static void -LineAA( Mat& img, Point pt1, Point pt2, const void* color ) +LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color ) { - int dx, dy; + int64 dx, dy; int ecount, scount = 0; int slope; - int ax, ay; - int x_step, y_step; - int i, j; + int64 ax, ay; + int64 x_step, y_step; + int64 i, j; int ep_table[9]; int cb = ((uchar*)color)[0], cg = ((uchar*)color)[1], cr = ((uchar*)color)[2], ca = ((uchar*)color)[3]; int _cb, _cg, _cr, _ca; int nch = img.channels(); uchar* ptr = img.data; size_t step = img.step; - Size size = img.size(); + Size2l size(img.cols, img.rows); if( !((nch == 1 || nch == 3 || nch == 4) && img.depth() == CV_8U) ) { - Line(img, pt1, pt2, color); + Line(img, Point((int)(pt1.x<> XY_SHIFT) - (pt1.x >> XY_SHIFT); + ecount = (int)((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); + pt1.y += ((y_step * j) >> XY_SHIFT) + (XY_ONE >> 1); slope = (y_step >> (XY_SHIFT - 5)) & 0x3f; slope ^= (y_step < 0 ? 0x3f : 0); @@ -356,12 +362,12 @@ LineAA( Mat& img, Point pt1, Point pt2, const void* color ) pt2.y ^= pt1.y & i; pt1.y ^= pt2.y & i; - x_step = (int) (((int64) dx << XY_SHIFT) / (ay | 1)); + x_step = (dx << XY_SHIFT) / (ay | 1); y_step = XY_ONE; pt2.y += XY_ONE; - ecount = (pt2.y >> XY_SHIFT) - (pt1.y >> XY_SHIFT); + ecount = (int)((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); + pt1.x += ((x_step * j) >> XY_SHIFT) + (XY_ONE >> 1); slope = (x_step >> (XY_SHIFT - 5)) & 0x3f; slope ^= (x_step < 0 ? 0x3f : 0); @@ -375,8 +381,8 @@ LineAA( Mat& img, Point pt1, Point pt2, const void* color ) /* Calc end point correction table */ { int t0 = slope << 7; - int t1 = ((0x78 - i) | 4) * slope; - int t2 = (j | 4) * slope; + int t1 = ((0x78 - (int)i) | 4) * slope; + int t2 = ((int)j | 4) * slope; ep_table[0] = 0; ep_table[8] = slope; @@ -630,23 +636,25 @@ LineAA( Mat& img, Point pt1, Point pt2, const void* color ) static void -Line2( Mat& img, Point pt1, Point pt2, const void* color ) +Line2( Mat& img, Point2l pt1, Point2l pt2, const void* color) { - int dx, dy; + int64 dx, dy; int ecount; - int ax, ay; - int i, j, x, y; - int x_step, y_step; + int64 ax, ay; + int64 i, j; + int x, y; + int64 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(), sizeScaled(size.width*XY_ONE, size.height*XY_ONE); + Size size = img.size(); //assert( img && (nch == 1 || nch == 3) && img.depth() == CV_8U ); + Size2l sizeScaled(((int64)size.width) << XY_SHIFT, ((int64)size.height) << XY_SHIFT); if( !clipLine( sizeScaled, pt1, pt2 )) return; @@ -670,8 +678,8 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) 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; + y_step = (dy << XY_SHIFT) / (ax | 1); + ecount = (int)((pt2.x - pt1.x) >> XY_SHIFT); } else { @@ -684,9 +692,9 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) pt2.y ^= pt1.y & i; pt1.y ^= pt2.y & i; - x_step = (int) (((int64) dx << XY_SHIFT) / (ay | 1)); + x_step = (dx << XY_SHIFT) / (ay | 1); y_step = XY_ONE; - ecount = (pt2.y - pt1.y) >> XY_SHIFT; + ecount = (int)((pt2.y - pt1.y) >> XY_SHIFT); } pt1.x += (XY_ONE >> 1); @@ -705,8 +713,8 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) tptr[2] = (uchar)cr; \ } - ICV_PUT_POINT((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT, - (pt2.y + (XY_ONE >> 1)) >> XY_SHIFT); + ICV_PUT_POINT((int)((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT), + (int)((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)); if( ax > ay ) { @@ -714,7 +722,7 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) while( ecount >= 0 ) { - ICV_PUT_POINT(pt1.x, pt1.y >> XY_SHIFT); + ICV_PUT_POINT((int)(pt1.x), (int)(pt1.y >> XY_SHIFT)); pt1.x++; pt1.y += y_step; ecount--; @@ -726,7 +734,7 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) while( ecount >= 0 ) { - ICV_PUT_POINT(pt1.x >> XY_SHIFT, pt1.y); + ICV_PUT_POINT((int)(pt1.x >> XY_SHIFT), (int)(pt1.y)); pt1.x += x_step; pt1.y++; ecount--; @@ -746,8 +754,8 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) tptr[0] = (uchar)cb; \ } - ICV_PUT_POINT((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT, - (pt2.y + (XY_ONE >> 1)) >> XY_SHIFT); + ICV_PUT_POINT((int)((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT), + (int)((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)); if( ax > ay ) { @@ -755,7 +763,7 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) while( ecount >= 0 ) { - ICV_PUT_POINT(pt1.x, pt1.y >> XY_SHIFT); + ICV_PUT_POINT((int)(pt1.x), (int)(pt1.y >> XY_SHIFT)); pt1.x++; pt1.y += y_step; ecount--; @@ -767,7 +775,7 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) while( ecount >= 0 ) { - ICV_PUT_POINT(pt1.x >> XY_SHIFT, pt1.y); + ICV_PUT_POINT((int)(pt1.x >> XY_SHIFT), (int)(pt1.y)); pt1.x += x_step; pt1.y++; ecount--; @@ -788,8 +796,8 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) tptr[j] = ((uchar*)color)[j]; \ } - ICV_PUT_POINT((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT, - (pt2.y + (XY_ONE >> 1)) >> XY_SHIFT); + ICV_PUT_POINT((int)((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT), + (int)((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)); if( ax > ay ) { @@ -797,7 +805,7 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) while( ecount >= 0 ) { - ICV_PUT_POINT(pt1.x, pt1.y >> XY_SHIFT); + ICV_PUT_POINT((int)(pt1.x), (int)(pt1.y >> XY_SHIFT)); pt1.x++; pt1.y += y_step; ecount--; @@ -809,7 +817,7 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color ) while( ecount >= 0 ) { - ICV_PUT_POINT(pt1.x >> XY_SHIFT, pt1.y); + ICV_PUT_POINT((int)(pt1.x >> XY_SHIFT), (int)(pt1.y)); pt1.x += x_step; pt1.y++; ecount--; @@ -917,13 +925,35 @@ sincos( int angle, float& cosval, float& sinval ) constructs polygon that represents elliptic arc. */ void ellipse2Poly( Point center, Size axes, int angle, + int arcStart, int arcEnd, + int delta, CV_OUT std::vector& pts ) +{ + vector _pts; + ellipse2Poly(Point2d(center.x, center.y), Size2d(axes.width, axes.height), angle, + arcStart, arcEnd, delta, _pts); + Point prevPt(INT_MIN, INT_MIN); + pts.resize(0); + for (unsigned int i = 0; i < _pts.size(); ++i) + { + Point pt; + pt.x = cvRound(_pts[i].x); + pt.y = cvRound(_pts[i].y); + if (pt != prevPt) { + pts.push_back(pt); + prevPt = pt; + } + } + + // If there are no points, it's a zero-size polygon + if( pts.size() == 1 ) + pts.push_back(pts[0]); +} + +void ellipse2Poly( Point2d center, Size2d axes, int angle, int arc_start, int arc_end, - int delta, vector& pts ) + int delta, vector& pts ) { float alpha, beta; - double size_a = axes.width, size_b = axes.height; - double cx = center.x, cy = center.y; - Point prevPt(INT_MIN,INT_MIN); int i; while( angle < 0 ) @@ -964,15 +994,12 @@ void ellipse2Poly( Point center, Size axes, int angle, if( angle < 0 ) angle += 360; - x = size_a * SinTable[450-angle]; - y = size_b * SinTable[angle]; - Point pt; - pt.x = cvRound( cx + x * alpha - y * beta ); - pt.y = cvRound( cy + x * beta + y * alpha ); - if( pt != prevPt ){ - pts.push_back(pt); - prevPt = pt; - } + x = axes.width * SinTable[450-angle]; + y = axes.height * SinTable[angle]; + Point2d pt; + pt.x = center.x + x * alpha - y * beta; + pt.y = center.y + x * beta + y * alpha; + pts.push_back(pt); } if( pts.size() == 1 ) @@ -981,16 +1008,37 @@ void ellipse2Poly( Point center, Size axes, int angle, static void -EllipseEx( Mat& img, Point center, Size axes, +EllipseEx( Mat& img, Point2l center, Size2l axes, int angle, int arc_start, int arc_end, const void* color, int thickness, int line_type ) { axes.width = std::abs(axes.width), axes.height = std::abs(axes.height); - int delta = (std::max(axes.width,axes.height)+(XY_ONE>>1))>>XY_SHIFT; + int delta = (int)((std::max(axes.width,axes.height)+(XY_ONE>>1))>>XY_SHIFT); delta = delta < 3 ? 90 : delta < 10 ? 30 : delta < 15 ? 18 : 5; - vector v; - ellipse2Poly( center, axes, angle, arc_start, arc_end, delta, v ); + vector _v; + ellipse2Poly( Point2d((double)center.x, (double)center.y), Size2d((double)axes.width, (double)axes.height), angle, arc_start, arc_end, delta, _v ); + + vector v; + Point2l prevPt(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF); + v.resize(0); + for (unsigned int i = 0; i < _v.size(); ++i) + { + Point2l pt; + pt.x = (int64)cvRound(_v[i].x / XY_ONE) << XY_SHIFT; + pt.y = (int64)cvRound(_v[i].y / XY_ONE) << XY_SHIFT; + pt.x += cvRound(_v[i].x - pt.x); + pt.y += cvRound(_v[i].y - pt.y); + if (pt != prevPt) { + v.push_back(pt); + prevPt = pt; + } + } + + // If there are no points, it's a zero-size polygon + if (v.size() == 1) { + v.assign(2, center); + } if( thickness >= 0 ) PolyLine( img, &v[0], (int)v.size(), false, color, thickness, line_type, XY_SHIFT ); @@ -1029,23 +1077,24 @@ EllipseEx( Mat& img, Point center, Size axes, /* filling convex polygon. v - array of vertices, ntps - number of points */ static void -FillConvexPoly( Mat& img, const Point* v, int npts, const void* color, int line_type, int shift ) +FillConvexPoly( Mat& img, const Point2l* v, int npts, const void* color, int line_type, int shift ) { struct { int idx, di; - int x, dx, ye; + int64 x, dx; + int ye; } edge[2]; - int delta = shift ? 1 << (shift - 1) : 0; - int i, y, imin = 0, left = 0, right = 1, x1, x2; + int delta = 1 << shift >> 1; + int i, y, imin = 0, left = 0, right = 1; int edges = npts; - int xmin, xmax, ymin, ymax; + int64 xmin, xmax, ymin, ymax; uchar* ptr = img.data; Size size = img.size(); int pix_size = (int)img.elemSize(); - Point p0; + Point2l p0; int delta1, delta2; if( line_type < CV_AA ) @@ -1063,7 +1112,7 @@ FillConvexPoly( Mat& img, const Point* v, int npts, const void* color, int line_ for( i = 0; i < npts; i++ ) { - Point p = v[i]; + Point2l p = v[i]; if( p.y < ymin ) { ymin = p.y; @@ -1082,10 +1131,10 @@ FillConvexPoly( Mat& img, const Point* v, int npts, const void* color, int line_ if( shift == 0 ) { Point pt0, pt1; - pt0.x = p0.x >> XY_SHIFT; - pt0.y = p0.y >> XY_SHIFT; - pt1.x = p.x >> XY_SHIFT; - pt1.y = p.y >> XY_SHIFT; + pt0.x = (int)(p0.x >> XY_SHIFT); + pt0.y = (int)(p0.y >> XY_SHIFT); + pt1.x = (int)(p.x >> XY_SHIFT); + pt1.y = (int)(p.y >> XY_SHIFT); Line( img, pt0, pt1, color, line_type ); } else @@ -1101,13 +1150,13 @@ FillConvexPoly( Mat& img, const Point* v, int npts, const void* color, int line_ ymin = (ymin + delta) >> shift; ymax = (ymax + delta) >> shift; - if( npts < 3 || xmax < 0 || ymax < 0 || xmin >= size.width || ymin >= size.height ) + if( npts < 3 || (int)xmax < 0 || (int)ymax < 0 || (int)xmin >= size.width || (int)ymin >= size.height ) return; ymax = MIN( ymax, size.height - 1 ); edge[0].idx = edge[1].idx = imin; - edge[0].ye = edge[1].ye = y = ymin; + edge[0].ye = edge[1].ye = y = (int)ymin; edge[0].di = 1; edge[1].di = npts - 1; @@ -1115,18 +1164,19 @@ FillConvexPoly( Mat& img, const Point* v, int npts, const void* color, int line_ do { - if( line_type < CV_AA || y < ymax || y == ymin ) + if( line_type < CV_AA || y < (int)ymax || y == (int)ymin ) { for( i = 0; i < 2; i++ ) { if( y >= edge[i].ye ) { int idx = edge[i].idx, di = edge[i].di; - int xs = 0, xe, ye, ty = 0; + int64 xs = 0, xe; + int ty = 0; for(;;) { - ty = (v[idx].y + delta) >> shift; + ty = (int)((v[idx].y + delta) >> shift); if( ty > y || edges == 0 ) break; xs = v[idx].x; @@ -1135,16 +1185,15 @@ FillConvexPoly( Mat& img, const Point* v, int npts, const void* color, int line_ edges--; } - ye = ty; xs <<= XY_SHIFT - shift; xe = v[idx].x << (XY_SHIFT - shift); /* no more edges */ - if( y >= ye ) + if( y >= ty) return; - edge[i].ye = ye; - edge[i].dx = ((xe - xs)*2 + (ye - y)) / (2 * (ye - y)); + edge[i].ye = ty; + edge[i].dx = ((xe - xs)*2 + (ty - y)) / (2 * (ty - y)); edge[i].x = xs; edge[i].idx = idx; } @@ -1157,13 +1206,10 @@ FillConvexPoly( Mat& img, const Point* v, int npts, const void* color, int line_ right ^= 1; } - x1 = edge[left].x; - x2 = edge[right].x; - if( y >= 0 ) { - int xx1 = (x1 + delta1) >> XY_SHIFT; - int xx2 = (x2 + delta2) >> XY_SHIFT; + int xx1 = (int)((edge[left].x + delta1) >> XY_SHIFT); + int xx2 = (int)((edge[right].x + delta2) >> XY_SHIFT); if( xx2 >= 0 && xx1 < size.width ) { @@ -1175,25 +1221,22 @@ FillConvexPoly( Mat& img, const Point* v, int npts, const void* color, int line_ } } - x1 += edge[left].dx; - x2 += edge[right].dx; - - edge[left].x = x1; - edge[right].x = x2; + edge[left].x += edge[left].dx; + edge[right].x += edge[right].dx; ptr += img.step; } - while( ++y <= ymax ); + while( ++y <= (int)ymax ); } /******** Arbitrary polygon **********/ static void -CollectPolyEdges( Mat& img, const Point* v, int count, vector& edges, +CollectPolyEdges( Mat& img, const Point2l* v, int count, vector& edges, const void* color, int line_type, int shift, Point offset ) { - int i, delta = offset.y + (shift ? 1 << (shift - 1) : 0); - Point pt0 = v[count-1], pt1; + int i, delta = offset.y + ((1 << shift) >> 1); + Point2l pt0 = v[count-1], pt1; pt0.x = (pt0.x + offset.x) << (XY_SHIFT - shift); pt0.y = (pt0.y + delta) >> shift; @@ -1201,7 +1244,7 @@ CollectPolyEdges( Mat& img, const Point* v, int count, vector& edges, for( i = 0; i < count; i++, pt0 = pt1 ) { - Point t0, t1; + Point2l t0, t1; PolyEdge edge; pt1 = v[i]; @@ -1213,7 +1256,7 @@ CollectPolyEdges( Mat& img, const Point* v, int count, vector& edges, t0.y = pt0.y; t1.y = pt1.y; t0.x = (pt0.x + (XY_ONE >> 1)) >> XY_SHIFT; t1.x = (pt1.x + (XY_ONE >> 1)) >> XY_SHIFT; - Line( img, t0, t1, color, line_type ); + Line( img, Point((int)(t0.x), (int)(t0.y)), Point((int)(t1.x), (int)(t1.y)), color, line_type ); } else { @@ -1228,14 +1271,14 @@ CollectPolyEdges( Mat& img, const Point* v, int count, vector& edges, if( pt0.y < pt1.y ) { - edge.y0 = pt0.y; - edge.y1 = pt1.y; + edge.y0 = (int)(pt0.y); + edge.y1 = (int)(pt1.y); edge.x = pt0.x; } else { - edge.y0 = pt1.y; - edge.y1 = pt0.y; + edge.y0 = (int)(pt1.y); + edge.y1 = (int)(pt0.y); edge.x = pt1.x; } edge.dx = (pt1.x - pt0.x) / (pt1.y - pt0.y); @@ -1261,7 +1304,8 @@ FillEdgeCollection( Mat& img, vector& edges, const void* color ) int i, y, total = (int)edges.size(); Size size = img.size(); PolyEdge* e; - int y_max = INT_MIN, x_max = INT_MIN, y_min = INT_MAX, x_min = INT_MAX; + int y_max = INT_MIN, y_min = INT_MAX; + int64 x_max = 0xFFFFFFFFFFFFFFFF, x_min = 0x7FFFFFFFFFFFFFFF; int pix_size = (int)img.elemSize(); if( total < 2 ) @@ -1273,7 +1317,7 @@ FillEdgeCollection( Mat& img, vector& edges, const void* color ) assert( e1.y0 < e1.y1 ); // Determine x-coordinate of the end of the edge. // (This is not necessary x-coordinate of any vertex in the array.) - int x1 = e1.x + (e1.y1 - e1.y0) * e1.dx; + int64 x1 = e1.x + (e1.y1 - e1.y0) * e1.dx; y_min = std::min( y_min, e1.y0 ); y_max = std::max( y_max, e1.y1 ); x_min = std::min( x_min, e1.x ); @@ -1282,7 +1326,7 @@ FillEdgeCollection( Mat& img, vector& edges, const void* color ) x_max = std::max( x_max, x1 ); } - if( y_max < 0 || y_min >= size.height || x_max < 0 || x_min >= (size.width<= size.height || x_max < 0 || x_min >= ((int64)size.width<& edges, const void* color ) { // convert x's from fixed-point to image coordinates uchar *timg = img.data + y * img.step; - int x1 = keep_prelast->x; - int x2 = prelast->x; + int x1, x2; - if( x1 > x2 ) + if (keep_prelast->x > prelast->x) { - int t = x1; - - x1 = x2; - x2 = t; + x1 = (int)((prelast->x + XY_ONE - 1) >> XY_SHIFT); + x2 = (int)(keep_prelast->x >> XY_SHIFT); + } + else + { + x1 = (int)((keep_prelast->x + XY_ONE - 1) >> XY_SHIFT); + x2 = (int)(prelast->x >> XY_SHIFT); } - - x1 = (x1 + XY_ONE - 1) >> XY_SHIFT; - x2 = x2 >> XY_SHIFT; // clip and draw the line if( x1 < size.width && x2 >= 0 ) @@ -1550,7 +1593,7 @@ Circle( Mat& img, Point center, int radius, const void* color, int fill ) static void -ThickLine( Mat& img, Point p0, Point p1, const void* color, +ThickLine( Mat& img, Point2l p0, Point2l p1, const void* color, int thickness, int line_type, int flags, int shift ) { static const double INV_XY_ONE = 1./XY_ONE; @@ -1570,7 +1613,7 @@ ThickLine( Mat& img, Point p0, Point p1, const void* color, 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 ); + Line( img, Point((int)(p0.x), (int)(p0.y)), Point((int)(p1.x), (int)(p1.y)), color, line_type ); } else Line2( img, p0, p1, color ); @@ -1580,7 +1623,7 @@ ThickLine( Mat& img, Point p0, Point p1, const void* color, } else { - Point pt[4], dp = Point(0,0); + Point2l pt[4], dp = Point2l(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; @@ -1611,13 +1654,13 @@ ThickLine( Mat& img, Point p0, Point p1, const void* color, 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; + center.x = (int)((p0.x + (XY_ONE>>1)) >> XY_SHIFT); + center.y = (int)((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), + EllipseEx( img, p0, Size2l(thickness, thickness), 0, 0, 360, color, -1, line_type ); } } @@ -1628,7 +1671,7 @@ ThickLine( Mat& img, Point p0, Point p1, const void* color, static void -PolyLine( Mat& img, const Point* v, int count, bool is_closed, +PolyLine( Mat& img, const Point2l* v, int count, bool is_closed, const void* color, int thickness, int line_type, int shift ) { @@ -1637,13 +1680,13 @@ PolyLine( Mat& img, const Point* v, int count, bool is_closed, int i = is_closed ? count - 1 : 0; int flags = 2 + !is_closed; - Point p0; + Point2l p0; CV_Assert( 0 <= shift && shift <= XY_SHIFT && thickness >= 0 ); p0 = v[i]; for( i = !is_closed; i < count; i++ ) { - Point p = v[i]; + Point2l p = v[i]; ThickLine( img, p0, p, color, thickness, line_type, flags, shift ); p0 = p; flags = 2; @@ -1700,7 +1743,7 @@ void rectangle( Mat& img, Point pt1, Point pt2, double buf[4]; scalarToRawData(color, buf, img.type(), 0); - Point pt[4]; + Point2l pt[4]; pt[0] = pt1; pt[1].x = pt2.x; @@ -1741,10 +1784,12 @@ void circle( Mat& img, Point center, int radius, if( thickness > 1 || line_type >= CV_AA || shift > 0 ) { - center.x <<= XY_SHIFT - shift; - center.y <<= XY_SHIFT - shift; - radius <<= XY_SHIFT - shift; - EllipseEx( img, center, Size(radius, radius), + Point2l _center(center.x, center.y); + int64 _radius(radius); + _center.x <<= XY_SHIFT - shift; + _center.y <<= XY_SHIFT - shift; + _radius <<= XY_SHIFT - shift; + EllipseEx( img, _center, Size2l(_radius, _radius), 0, 0, 360, buf, thickness, line_type ); } else @@ -1768,12 +1813,14 @@ void ellipse( Mat& img, Point center, Size axes, int _angle = cvRound(angle); int _start_angle = cvRound(start_angle); int _end_angle = cvRound(end_angle); - center.x <<= XY_SHIFT - shift; - center.y <<= XY_SHIFT - shift; - axes.width <<= XY_SHIFT - shift; - axes.height <<= XY_SHIFT - shift; - - EllipseEx( img, center, axes, _angle, _start_angle, + Point2l _center(center.x, center.y); + Size2l _axes(axes.width, axes.height); + _center.x <<= XY_SHIFT - shift; + _center.y <<= XY_SHIFT - shift; + _axes.width <<= XY_SHIFT - shift; + _axes.height <<= XY_SHIFT - shift; + + EllipseEx( img, _center, _axes, _angle, _start_angle, _end_angle, buf, thickness, line_type ); } @@ -1790,10 +1837,14 @@ void ellipse(Mat& img, const RotatedRect& box, const Scalar& color, scalarToRawData(color, buf, img.type(), 0); int _angle = cvRound(box.angle); - Point center(cvRound(box.center.x*(1 << XY_SHIFT)), - cvRound(box.center.y*(1 << XY_SHIFT))); - Size axes(cvRound(box.size.width*(1 << (XY_SHIFT - 1))), - cvRound(box.size.height*(1 << (XY_SHIFT - 1)))); + Point2l center(cvRound(box.center.x), + cvRound(box.center.y)); + center.x = (center.x << XY_SHIFT) + cvRound((box.center.x - center.x)*XY_ONE); + center.y = (center.y << XY_SHIFT) + cvRound((box.center.y - center.y)*XY_ONE); + Size2l axes(cvRound(box.size.width), + cvRound(box.size.height)); + axes.width = (axes.width << (XY_SHIFT - 1)) + cvRound((box.size.width - axes.width)*(XY_ONE>>1)); + axes.height = (axes.height << (XY_SHIFT - 1)) + cvRound((box.size.height - axes.height)*(XY_ONE>>1)); EllipseEx( img, center, axes, _angle, 0, 360, buf, thickness, lineType ); } @@ -1876,7 +1927,10 @@ void fillConvexPoly( Mat& img, const Point* pts, int npts, double buf[4]; CV_Assert( 0 <= shift && shift <= XY_SHIFT ); scalarToRawData(color, buf, img.type(), 0); - FillConvexPoly( img, pts, npts, buf, line_type, shift ); + vector _pts; + for( int n = 0; n < npts; n++ ) + _pts.push_back(Point2l(pts[n].x, pts[n].y)); + FillConvexPoly( img, _pts.data(), npts, buf, line_type, shift ); } @@ -1900,7 +1954,12 @@ void fillPoly( Mat& img, const Point** pts, const int* npts, int ncontours, edges.reserve( total + 1 ); for( i = 0; i < ncontours; i++ ) - CollectPolyEdges( img, pts[i], npts[i], edges, buf, line_type, shift, offset ); + { + vector _pts; + for( int n = 0; n < npts[i]; n++ ) + _pts.push_back(Point2l(pts[i][n].x, pts[i][n].y)); + CollectPolyEdges( img, _pts.data(), npts[i], edges, buf, line_type, shift, offset ); + } FillEdgeCollection(img, edges, buf); } @@ -1920,7 +1979,12 @@ void polylines( Mat& img, const Point** pts, const int* npts, int ncontours, boo scalarToRawData( color, buf, img.type(), 0 ); for( int i = 0; i < ncontours; i++ ) - PolyLine( img, pts[i], npts[i], isClosed, buf, thickness, line_type, shift ); + { + vector _pts; + for( int n = 0; n < npts[i]; n++ ) + _pts.push_back(Point2l(pts[i][n].x, pts[i][n].y)); + PolyLine( img, _pts.data(), npts[i], isClosed, buf, thickness, line_type, shift ); + } } @@ -2156,23 +2220,23 @@ void putText( Mat& img, const string& text, Point org, if( bottomLeftOrigin ) vscale = -vscale; - int view_x = org.x << XY_SHIFT; - int view_y = (org.y << XY_SHIFT) + base_line*vscale; - vector pts; + int64 view_x = (int64)org.x << XY_SHIFT; + int64 view_y = ((int64)org.y << XY_SHIFT) + base_line*vscale; + vector pts; pts.reserve(1 << 10); const char **faces = cv::g_HersheyGlyphs; for( int i = 0; i < (int)text.size(); i++ ) { int c = (uchar)text[i]; - Point p; + Point2l p; readCheck(c, i, text, fontFace); const char* ptr = faces[ascii[(c-' ')+1]]; p.x = (uchar)ptr[0] - 'R'; p.y = (uchar)ptr[1] - 'R'; - int dx = p.y*hscale; + int64 dx = p.y*hscale; view_x -= p.x*hscale; pts.resize(0); @@ -2191,7 +2255,7 @@ void putText( Mat& img, const string& text, Point org, p.x = (uchar)ptr[0] - 'R'; p.y = (uchar)ptr[1] - 'R'; ptr += 2; - pts.push_back(Point(p.x*hscale + view_x, p.y*vscale + view_y)); + pts.push_back(Point2l(p.x*hscale + view_x, p.y*vscale + view_y)); } } view_x += dx; @@ -2310,7 +2374,7 @@ cvDrawContours( void* _img, CvSeq* contour, CvSeq *contour0 = contour, *h_next = 0; CvTreeNodeIterator iterator; cv::vector edges; - cv::vector pts; + cv::vector pts; cv::Scalar externalColor = _externalColor, holeColor = _holeColor; cv::Mat img = cv::cvarrToMat(_img); cv::Point offset = _offset; @@ -2434,7 +2498,7 @@ cvEllipse2Poly( CvPoint center, CvSize axes, int angle, int arc_start, int arc_end, CvPoint* _pts, int delta ) { cv::vector pts; - cv::ellipse2Poly( center, axes, angle, arc_start, arc_end, delta, pts ); + cv::ellipse2Poly( cv::Point(center), cv::Size(axes), angle, arc_start, arc_end, delta, pts ); memcpy( _pts, &pts[0], pts.size()*sizeof(_pts[0]) ); return (int)pts.size(); } diff --git a/modules/highgui/test/test_drawing.cpp b/modules/highgui/test/test_drawing.cpp index 46bffbebe9..9079e042ed 100644 --- a/modules/highgui/test/test_drawing.cpp +++ b/modules/highgui/test/test_drawing.cpp @@ -409,9 +409,143 @@ int CV_DrawingTest_C::checkLineIterator( Mat& _img ) return 0; } +class CV_DrawingTest_Far : public CV_DrawingTest_CPP +{ +public: + CV_DrawingTest_Far() {} +protected: + virtual void draw(Mat& img); +}; + +void CV_DrawingTest_Far::draw(Mat& img) +{ + Size imgSize(32768 + 600, 400); + img.create(imgSize, CV_8UC3); + + vector polyline(4); + polyline[0] = Point(32768 + 0, 0); + polyline[1] = Point(imgSize.width, 0); + polyline[2] = Point(imgSize.width, imgSize.height); + polyline[3] = Point(32768 + 0, imgSize.height); + const Point* pts = &polyline[0]; + int n = (int)polyline.size(); + fillPoly(img, &pts, &n, 1, Scalar::all(255)); + + Point p1(32768 + 1, 1), p2(32768 + 3, 3); + if (clipLine(Rect(32768 + 0, 0, imgSize.width, imgSize.height), p1, p2) && clipLine(imgSize, p1, p2)) + circle(img, Point(32768 + 300, 100), 40, Scalar(0, 0, 255), 3); // draw + + p2 = Point(32768 + 3, imgSize.height + 1000); + if (clipLine(Rect(32768 + 0, 0, imgSize.width, imgSize.height), p1, p2) && clipLine(imgSize, p1, p2)) + circle(img, Point(65536 + 500, 300), 50, cvColorToScalar(255, CV_8UC3), 5, 8, 1); // draw + + p1 = Point(imgSize.width, 1), p2 = Point(imgSize.width, 3); + if (clipLine(Rect(32768 + 0, 0, imgSize.width, imgSize.height), p1, p2) && clipLine(imgSize, p1, p2)) + circle(img, Point(32768 + 390, 100), 10, Scalar(0, 0, 255), 3); // not draw + + p1 = Point(imgSize.width - 1, 1), p2 = Point(imgSize.width, 3); + if (clipLine(Rect(32768 + 0, 0, imgSize.width, imgSize.height), p1, p2) && clipLine(imgSize, p1, p2)) + ellipse(img, Point(32768 + 390, 100), Size(20, 30), 60, 0, 220.0, Scalar(0, 200, 0), 4); //draw + + ellipse(img, RotatedRect(Point(32768 + 100, 200), Size(200, 100), 160), Scalar(200, 200, 255), 5); + + polyline.clear(); + ellipse2Poly(Point(32768 + 430, 180), Size(100, 150), 30, 0, 150, 20, polyline); + pts = &polyline[0]; + n = (int)polyline.size(); + polylines(img, &pts, &n, 1, false, Scalar(0, 0, 150), 4, CV_AA); + n = 0; + for (vector::const_iterator it = polyline.begin(); n < (int)polyline.size() - 1; ++it, n++) + { + line(img, *it, *(it + 1), Scalar(50, 250, 100)); + } + + polyline.clear(); + ellipse2Poly(Point(32768 + 500, 300), Size(50, 80), 0, 0, 180, 10, polyline); + pts = &polyline[0]; + n = (int)polyline.size(); + polylines(img, &pts, &n, 1, true, Scalar(100, 200, 100), 20); + fillConvexPoly(img, pts, n, Scalar(0, 80, 0)); + + polyline.resize(8); + // external rectengular + polyline[0] = Point(32768 + 0, 0); + polyline[1] = Point(32768 + 80, 0); + polyline[2] = Point(32768 + 80, 80); + polyline[3] = Point(32768 + 0, 80); + // internal rectangular + polyline[4] = Point(32768 + 20, 20); + polyline[5] = Point(32768 + 60, 20); + polyline[6] = Point(32768 + 60, 60); + polyline[7] = Point(32768 + 20, 60); + const Point* ppts[] = { &polyline[0], &polyline[0] + 4 }; + int pn[] = { 4, 4 }; + fillPoly(img, ppts, pn, 2, Scalar(100, 100, 0), 8, 0, Point(500, 20)); + + rectangle(img, Point(32768 + 0, 300), Point(32768 + 50, 398), Scalar(0, 0, 255)); + + string text1 = "OpenCV"; + int baseline = 0, thickness = 3, fontFace = FONT_HERSHEY_SCRIPT_SIMPLEX; + float fontScale = 2; + Size textSize = getTextSize(text1, fontFace, fontScale, thickness, &baseline); + baseline += thickness; + Point textOrg((32768 + img.cols - textSize.width) / 2, (img.rows + textSize.height) / 2); + rectangle(img, textOrg + Point(0, baseline), textOrg + Point(textSize.width, -textSize.height), Scalar(0, 0, 255)); + line(img, textOrg + Point(0, thickness), textOrg + Point(textSize.width, thickness), Scalar(0, 0, 255)); + putText(img, text1, textOrg, fontFace, fontScale, Scalar(150, 0, 150), thickness, 8); + + string text2 = "abcdefghijklmnopqrstuvwxyz1234567890"; + Scalar color(200, 0, 0); + fontScale = 0.5, thickness = 1; + int dist = 5; + + textSize = getTextSize(text2, FONT_HERSHEY_SIMPLEX, fontScale, thickness, &baseline); + textOrg = Point(32768 + 5, 5) + Point(0, textSize.height + dist); + putText(img, text2, textOrg, FONT_HERSHEY_SIMPLEX, fontScale, color, thickness, CV_AA); + + fontScale = 1; + textSize = getTextSize(text2, FONT_HERSHEY_PLAIN, fontScale, thickness, &baseline); + textOrg += Point(0, textSize.height + dist); + putText(img, text2, textOrg, FONT_HERSHEY_PLAIN, fontScale, color, thickness, CV_AA); + + fontScale = 0.5; + textSize = getTextSize(text2, FONT_HERSHEY_DUPLEX, fontScale, thickness, &baseline); + textOrg += Point(0, textSize.height + dist); + putText(img, text2, textOrg, FONT_HERSHEY_DUPLEX, fontScale, color, thickness, CV_AA); + + textSize = getTextSize(text2, FONT_HERSHEY_COMPLEX, fontScale, thickness, &baseline); + textOrg += Point(0, textSize.height + dist); + putText(img, text2, textOrg, FONT_HERSHEY_COMPLEX, fontScale, color, thickness, CV_AA); + + textSize = getTextSize(text2, FONT_HERSHEY_TRIPLEX, fontScale, thickness, &baseline); + textOrg += Point(0, textSize.height + dist); + putText(img, text2, textOrg, FONT_HERSHEY_TRIPLEX, fontScale, color, thickness, CV_AA); + + fontScale = 1; + textSize = getTextSize(text2, FONT_HERSHEY_COMPLEX_SMALL, fontScale, thickness, &baseline); + textOrg += Point(0, 180) + Point(0, textSize.height + dist); + putText(img, text2, textOrg, FONT_HERSHEY_COMPLEX_SMALL, fontScale, color, thickness, CV_AA); + + textSize = getTextSize(text2, FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale, thickness, &baseline); + textOrg += Point(0, textSize.height + dist); + putText(img, text2, textOrg, FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale, color, thickness, CV_AA); + + textSize = getTextSize(text2, FONT_HERSHEY_SCRIPT_COMPLEX, fontScale, thickness, &baseline); + textOrg += Point(0, textSize.height + dist); + putText(img, text2, textOrg, FONT_HERSHEY_SCRIPT_COMPLEX, fontScale, color, thickness, CV_AA); + + dist = 15, fontScale = 0.5; + textSize = getTextSize(text2, FONT_ITALIC, fontScale, thickness, &baseline); + textOrg += Point(0, textSize.height + dist); + putText(img, text2, textOrg, FONT_ITALIC, fontScale, color, thickness, CV_AA); + + img = img(Rect(32768, 0, 600, 400)).clone(); +} + #ifdef HAVE_JPEG TEST(Highgui_Drawing, cpp_regression) { CV_DrawingTest_CPP test; test.safe_run(); } TEST(Highgui_Drawing, c_regression) { CV_DrawingTest_C test; test.safe_run(); } +TEST(Highgui_Drawing, far_regression) { CV_DrawingTest_Far test; test.safe_run(); } #endif class CV_FillConvexPolyTest : public cvtest::BaseTest