From 9dedbff713cf86766153bafeb51fb3a3bdd6feef Mon Sep 17 00:00:00 2001 From: Hugo Date: Thu, 12 Apr 2018 18:15:27 +0300 Subject: [PATCH 1/6] Add width parameter to rectangle --- Tests/images/imagedraw_rectangle_width.png | Bin 0 -> 228 bytes .../images/imagedraw_rectangle_width_fill.png | Bin 0 -> 239 bytes Tests/test_imagedraw.py | 24 ++++++++++++++++++ docs/reference/ImageDraw.rst | 5 +++- src/PIL/ImageDraw.py | 4 +-- src/_imaging.c | 7 ++--- src/libImaging/Draw.c | 18 ++++++++----- src/libImaging/Imaging.h | 2 +- 8 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 Tests/images/imagedraw_rectangle_width.png create mode 100644 Tests/images/imagedraw_rectangle_width_fill.png diff --git a/Tests/images/imagedraw_rectangle_width.png b/Tests/images/imagedraw_rectangle_width.png new file mode 100644 index 0000000000000000000000000000000000000000..e39659921fce6d3398d4eab5199f7bb7591c6a60 GIT binary patch literal 228 zcmeAS@N?(olHy`uVBq!ia0vp^DIm56&GN!3hI>xN`>SPuia@}o%&%|l$&H@bY0qZO{K>YF2?(3+AA7sC@VCDI?llfn og%6g_XZuzV*%$$W5c?Sp@-DAsdZpXg{2wIX>FVdQ&MBb@02WzQ$p8QV literal 0 HcmV?d00001 diff --git a/Tests/images/imagedraw_rectangle_width_fill.png b/Tests/images/imagedraw_rectangle_width_fill.png new file mode 100644 index 0000000000000000000000000000000000000000..d5243c608b62e7c92b24af025e853bb8323d76c7 GIT binary patch literal 239 zcmeAS@N?(olHy`uVBq!ia0vp^DImmdKI;Vst07nl> ABLDyZ literal 0 HcmV?d00001 diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index 1c8fe3153..cd4eb2780 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -343,6 +343,30 @@ class TestImageDraw(PillowTestCase): # Assert self.assert_image_similar(im, Image.open(expected), 1) + def test_rectangle_width(self): + # Arrange + im = Image.new("RGB", (W, H)) + draw = ImageDraw.Draw(im) + expected = "Tests/images/imagedraw_rectangle_width.png" + + # Act + draw.rectangle(BBOX1, outline="green", width=5) + + # Assert + self.assert_image_equal(im, Image.open(expected)) + + def test_rectangle_width_fill(self): + # Arrange + im = Image.new("RGB", (W, H)) + draw = ImageDraw.Draw(im) + expected = "Tests/images/imagedraw_rectangle_width_fill.png" + + # Act + draw.rectangle(BBOX1, fill="blue", outline="green", width=5) + + # Assert + self.assert_image_equal(im, Image.open(expected)) + def test_floodfill(self): # Arrange im = Image.new("RGB", (W, H)) diff --git a/docs/reference/ImageDraw.rst b/docs/reference/ImageDraw.rst index 6057712e2..7b28aafb0 100644 --- a/docs/reference/ImageDraw.rst +++ b/docs/reference/ImageDraw.rst @@ -220,7 +220,7 @@ Methods :param outline: Color to use for the outline. :param fill: Color to use for the fill. -.. py:method:: PIL.ImageDraw.ImageDraw.rectangle(xy, fill=None, outline=None) +.. py:method:: PIL.ImageDraw.ImageDraw.rectangle(xy, fill=None, outline=None, width=0) Draws a rectangle. @@ -229,6 +229,9 @@ Methods is just outside the drawn rectangle. :param outline: Color to use for the outline. :param fill: Color to use for the fill. + :param width: The line width, in pixels. + + .. versionadded:: 5.2.0 .. py:method:: PIL.ImageDraw.ImageDraw.shape(shape, fill=None, outline=None) diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py index 5bc890252..1bbb6e6a6 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -186,13 +186,13 @@ class ImageDraw(object): if ink is not None: self.draw.draw_polygon(xy, ink, 0) - def rectangle(self, xy, fill=None, outline=None): + def rectangle(self, xy, fill=None, outline=None, width=0): """Draw a rectangle.""" ink, fill = self._getink(outline, fill) if fill is not None: self.draw.draw_rectangle(xy, fill, 1) if ink is not None: - self.draw.draw_rectangle(xy, ink, 0) + self.draw.draw_rectangle(xy, ink, 0, width) def _multiline_check(self, text): """Draw text.""" diff --git a/src/_imaging.c b/src/_imaging.c index 5004becee..3cced9a0f 100644 --- a/src/_imaging.c +++ b/src/_imaging.c @@ -2730,7 +2730,7 @@ _draw_lines(ImagingDrawObject* self, PyObject* args) if (width <= 1) { double *p = NULL; - for (i = 0; i < n-1; i++) { + for (i = 0; i < n-1; i++) { p = &xy[i+i]; if (ImagingDrawLine( self->image->image, @@ -2931,7 +2931,8 @@ _draw_rectangle(ImagingDrawObject* self, PyObject* args) PyObject* data; int ink; int fill = 0; - if (!PyArg_ParseTuple(args, "Oi|i", &data, &ink, &fill)) + int width = 0; + if (!PyArg_ParseTuple(args, "Oi|ii", &data, &ink, &fill, &width)) return NULL; n = PyPath_Flatten(data, &xy); @@ -2945,7 +2946,7 @@ _draw_rectangle(ImagingDrawObject* self, PyObject* args) n = ImagingDrawRectangle(self->image->image, (int) xy[0], (int) xy[1], (int) xy[2], (int) xy[3], - &ink, fill, self->blend + &ink, fill, width, self->blend ); free(xy); diff --git a/src/libImaging/Draw.c b/src/libImaging/Draw.c index 7b7c5fac0..fee1cac63 100644 --- a/src/libImaging/Draw.c +++ b/src/libImaging/Draw.c @@ -634,8 +634,9 @@ ImagingDrawWideLine(Imaging im, int x0, int y0, int x1, int y1, int ImagingDrawRectangle(Imaging im, int x0, int y0, int x1, int y1, - const void* ink_, int fill, int op) + const void* ink_, int fill, int width, int op) { + int i; int y; int tmp; DRAW* draw; @@ -662,13 +663,16 @@ ImagingDrawRectangle(Imaging im, int x0, int y0, int x1, int y1, draw->hline(im, x0, y, x1, ink); } else { - /* outline */ - draw->line(im, x0, y0, x1, y0, ink); - draw->line(im, x1, y0, x1, y1, ink); - draw->line(im, x1, y1, x0, y1, ink); - draw->line(im, x0, y1, x0, y0, ink); - + if (width == 0) { + width = 1; + } + for (i = 0; i < width; i++) { + draw->hline(im, x0, y0+i, x1, ink); + draw->hline(im, x0, y1-i, x1, ink); + draw->line(im, x1-i, y0, x1-i, y1, ink); + draw->line(im, x0+i, y1, x0+i, y0, ink); + } } return 0; diff --git a/src/libImaging/Imaging.h b/src/libImaging/Imaging.h index 6b553c928..4588602b1 100644 --- a/src/libImaging/Imaging.h +++ b/src/libImaging/Imaging.h @@ -368,7 +368,7 @@ extern int ImagingDrawPoint(Imaging im, int x, int y, const void* ink, int op); extern int ImagingDrawPolygon(Imaging im, int points, int *xy, const void* ink, int fill, int op); extern int ImagingDrawRectangle(Imaging im, int x0, int y0, int x1, int y1, - const void* ink, int fill, int op); + const void* ink, int fill, int width, int op); /* Level 2 graphics (WORK IN PROGRESS) */ extern ImagingOutline ImagingOutlineNew(void); From d6e3ef85c2e2780410ca60258ee0e95682947ccd Mon Sep 17 00:00:00 2001 From: Hugo Date: Fri, 13 Apr 2018 08:37:54 +0300 Subject: [PATCH 2/6] Add width parameter to arc, chord, ellipse, pieslice --- Tests/images/imagedraw_arc_width.png | Bin 0 -> 439 bytes Tests/images/imagedraw_arc_width_fill.png | Bin 0 -> 438 bytes Tests/images/imagedraw_chord_width.png | Bin 0 -> 488 bytes Tests/images/imagedraw_chord_width_fill.png | Bin 0 -> 507 bytes Tests/images/imagedraw_ellipse_width.png | Bin 0 -> 452 bytes Tests/images/imagedraw_ellipse_width_fill.png | Bin 0 -> 477 bytes Tests/images/imagedraw_pieslice_width.png | Bin 0 -> 488 bytes .../images/imagedraw_pieslice_width_fill.png | Bin 0 -> 500 bytes Tests/test_imagedraw.py | 96 ++++++++++ docs/reference/ImageDraw.rst | 20 ++- src/PIL/ImageDraw.py | 16 +- src/_imaging.c | 22 ++- src/libImaging/Draw.c | 166 ++++++++++-------- src/libImaging/Imaging.h | 9 +- 14 files changed, 227 insertions(+), 102 deletions(-) create mode 100644 Tests/images/imagedraw_arc_width.png create mode 100644 Tests/images/imagedraw_arc_width_fill.png create mode 100644 Tests/images/imagedraw_chord_width.png create mode 100644 Tests/images/imagedraw_chord_width_fill.png create mode 100644 Tests/images/imagedraw_ellipse_width.png create mode 100644 Tests/images/imagedraw_ellipse_width_fill.png create mode 100644 Tests/images/imagedraw_pieslice_width.png create mode 100644 Tests/images/imagedraw_pieslice_width_fill.png diff --git a/Tests/images/imagedraw_arc_width.png b/Tests/images/imagedraw_arc_width.png new file mode 100644 index 0000000000000000000000000000000000000000..ff3f1f0b21c94c490169ef922a606ba3e7ce0156 GIT binary patch literal 439 zcmV;o0Z9IdP)4zkE(~PRqzagFhNke}zOeEmIku_@0000000000006)^=XrJy;l1zP z%a3UE&=YG`qX&1ap_wjU&WnvM70y`GOGU(CxW+ouaX7|MLO#$%sX>`8+Ts3HYFws^ z^#*?#S}LTmUQVmIr9u~Lzf$2`hSN)hDAx0|+MrY@V(nTgT7C`ZlE>O+T19!R4PF2j zv@>g`X%*bFQYvHZy#_-%vo>3U!7@xCRsyjSh?PLB1Y#u+E1~(UgUGMPR2HDn2eX z>*a^Xdv3f4de~#SH^e1|=Xyl?E{nDRXS++TD;;O@-TJss+f?uJ!K!9^9$nE(5&Fxo z-U(XRy)}Mif!^VlOPxesS4QOqXo+kr(-qa--&TAwIoEjYBAaV$`VHK-W^TQ_h3j3U z=G2Yf;+hrbM$TS)FhO#efOca9=MgW3Fs6+{9aAsVTyuQ#@Z*kGo#*$m=P%fum%66d zZj*RlS9MsE*|d69uk{f!uXD6Fmf3tteK9BIRd(TduND1YZ9dyhKK()8;_{iG@1JVq zCq?M*54!t&DsKDUz3dhMO+4>!M8 zeR{qsvgS(uzikt~#`={^-?(>z*`6QQ)Qb1*`u;{}%9l^?3rzA?)A6n~-f+h2WW eD=^TZ;J_{Y`lP6ULeDZAkcg+NpUXO@geCyd0?HBq literal 0 HcmV?d00001 diff --git a/Tests/images/imagedraw_chord_width.png b/Tests/images/imagedraw_chord_width.png new file mode 100644 index 0000000000000000000000000000000000000000..33a59b487c4e685f1a12c95323ea861fa17997e3 GIT binary patch literal 488 zcmeAS@N?(olHy`uVBq!ia0vp^DImaSW-L^LF;ZzGed+*1LcI z*Dq`LS}nSC!lrMZy-kXjP2kyfFtY=w0SPp`ys_=Zws(#(A7AYKvwMO2=ZF{MbPkr+~hDtPJe=kJXoZ;1VXLgvm&S$5%qzD0oRRgfl+tSMcDvP46ZwAPdQQEA-$DXYLVwSy zSo-C|v}s!u+Kd$ZDIyU+|$+1Wt~$(69A!*=T-m! literal 0 HcmV?d00001 diff --git a/Tests/images/imagedraw_chord_width_fill.png b/Tests/images/imagedraw_chord_width_fill.png new file mode 100644 index 0000000000000000000000000000000000000000..809c3ea1cdffd6aea9bc288f40f8349edb859826 GIT binary patch literal 507 zcmeAS@N?(olHy`uVBq!ia0vp^DImI;vs!9fmsl!0SRo7IWBm7qO425`@5I*+*K;>CGLJ1-(5ql zO}AcmFmCnB*M}=NeT-cB?9bE5SI_^C@nx;GJhgZ7w_uLv&E8)Z+f1_#4p(3Q%3J!x z(v|Nry?<@;`w-ug5?Az3=u}p^MV#{2nw2SgvsabY?9xw`-e>kces~#`sO77}e z|8tYt?5y4iPqiOs{g7g~-(X72x`yK178we?I_o%-~%XeL*tv{j9yuj{$11=I9@%jTaf_xjx&$G_5N z#l737=5EY$7fOE|J@3y~+aI6%tL?WwNsK++IZye9*b+|e`#Vp~@&4Ww-^%;w{zHxL udlRQ0iCv)e+dnq@YS}5Icwk_7Q2&Y3-o4D~?~4$5kc6kJpUXO@geCx&%JG~4 literal 0 HcmV?d00001 diff --git a/Tests/images/imagedraw_ellipse_width.png b/Tests/images/imagedraw_ellipse_width.png new file mode 100644 index 0000000000000000000000000000000000000000..ec0ca6731f69b8728a41a59ae2cd8ebaa0cb71c5 GIT binary patch literal 452 zcmeAS@N?(olHy`uVBq!ia0vp^DIm-il6&m%Sud>DbwD@2Gjxt7H&;1(bid$7#YdI$gZMA$hCvtzzL+_mb^ENzl=Dj-MM#v1sH77sleP5UH zd4|=Ry@5-=Xy?`(*mE#{6We3EQ%e(h?SI}8iyZ@*5m+3DqXc(+l@Q=11{YnQe^tzKiRzFF?;nNRzfgub1aCptm; zT2^+!J|69%ea<|eNhC^Hm$i#o^istG)&HDQ%8&3%nJ#FA1JFQ-otJ;S@ zd+XF0k^PC1R_fEY>3>_p;2QC1{gSd1` z!9IWXbp4fKB~ocmpZ@EgZoQQ8P8i<bP0l+XkKH;l^C literal 0 HcmV?d00001 diff --git a/Tests/images/imagedraw_ellipse_width_fill.png b/Tests/images/imagedraw_ellipse_width_fill.png new file mode 100644 index 0000000000000000000000000000000000000000..9b7be602916cce5f30f0e305add360c4939b3955 GIT binary patch literal 477 zcmeAS@N?(olHy`uVBq!ia0vp^DImY3` zviDB&_x4bs%kle!>~d{gTNE?{XBVHFSsHpZ+jhov!Q1=Q*W|98-J>RdZ}~Fa;{w-q z?FsS8kH6!hw#GyD+M-p*4fmRE>hcMlQrXW z^<^shkBzRZl?snrw4tqW)pzmJ|CVx`o_A%_^hYPJ7MlOr{w2{e|HGqwrw)JGd+lDZ zrQF9eo9xZKs#DH;t>AsV#q`JGoRCv9pT;*os*7ynY?ZsZZZVt?^Q_@Yh6KW*@f?wtDA@Xwl@IWdp+-PkN7lE`a(-*~6mUXk~l>t-%J zce=>dCGo7@%60Q9Pk-Gmb@xos)2CiqM@|RKpKiD^!|F`fl<9vvryDQjoD=5vK&GbY zXQ!f#KUe#%m4%p-bCtdV&N!UHx3v IIVCg!0J1dLjsO4v literal 0 HcmV?d00001 diff --git a/Tests/images/imagedraw_pieslice_width.png b/Tests/images/imagedraw_pieslice_width.png new file mode 100644 index 0000000000000000000000000000000000000000..a83c4ab7b3469f0d2171148d31a4c7836311b50c GIT binary patch literal 488 zcmVP)BCwwrp=djxM5P(Q7Xf-4&n^WH0;OpIQMV$1fA81;PH}Fd;i-} zc4z&SlzT3R#0&gp$)s9xSch#jOv-oV$_r~QDQn7UcqS?9G?T*mY%A*&PRa=Do=LT$ zyWy$?VNJA^=?yVFEYtH0k=>hRpQs!+W^PQl(QmW0elk!?O&}GR?0Kr^zvt-!KgDu++TyWSW{~ zNDrxJ)_$pNrXiSb@U0D7s)=LmROu*Hx1}!Dvr?t`mSIn+;x$FF)+b%OLMKJ6zgeoK zJPpSskM(F;6`hLVv5KB&2<^;zFs&-z;J9bq5F4xTtcW0-S(O*mGi8@y#nKgHm7S6m zW0jTu-tfdS!K&jp)v_4V~kuDzoKAJ{ar z)V(~{LlkT8D$CBt_G4Q&vrN65+Y-`cDDP$7z)5%-M)gYg#;ZTXjsKK(I?W_JBhS_8 z`nPhAtJ$PI9p_ZOsB%)RW5tcPQ+i3X+hjV6l;6Fv$$Y1fwMh`t%RTt?9hC>w(#D(~ qYjIhv&QJjW0000000000{9j*)= x0`` and ``y1 >= y0``. :param outline: Color to use for the outline. :param fill: Color to use for the fill. + :param width: The line width, in pixels. -.. py:method:: PIL.ImageDraw.ImageDraw.ellipse(xy, fill=None, outline=None) + .. versionadded:: 5.2.0 + +.. py:method:: PIL.ImageDraw.ImageDraw.ellipse(xy, fill=None, outline=None, width=0) Draws an ellipse inside the given bounding box. @@ -170,6 +176,9 @@ Methods where ``x1 >= x0`` and ``y1 >= y0``. :param outline: Color to use for the outline. :param fill: Color to use for the fill. + :param width: The line width, in pixels. + + .. versionadded:: 5.2.0 .. py:method:: PIL.ImageDraw.ImageDraw.line(xy, fill=None, width=0) @@ -185,7 +194,7 @@ Methods .. note:: This option was broken until version 1.1.6. -.. py:method:: PIL.ImageDraw.ImageDraw.pieslice(xy, start, end, fill=None, outline=None) +.. py:method:: PIL.ImageDraw.ImageDraw.pieslice(xy, start, end, fill=None, outline=None, width=0) Same as arc, but also draws straight lines between the end points and the center of the bounding box. @@ -198,6 +207,9 @@ Methods :param end: Ending angle, in degrees. :param fill: Color to use for the fill. :param outline: Color to use for the outline. + :param width: The outer line width, in pixels. + + .. versionadded:: 5.2.0 .. py:method:: PIL.ImageDraw.ImageDraw.point(xy, fill=None) diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py index 1bbb6e6a6..23a666e76 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -118,11 +118,11 @@ class ImageDraw(object): fill = self.draw.draw_ink(fill, self.mode) return ink, fill - def arc(self, xy, start, end, fill=None): + def arc(self, xy, start, end, fill=None, width=0): """Draw an arc.""" ink, fill = self._getink(fill) if ink is not None: - self.draw.draw_arc(xy, start, end, ink) + self.draw.draw_arc(xy, start, end, ink, width) def bitmap(self, xy, bitmap, fill=None): """Draw a bitmap.""" @@ -133,21 +133,21 @@ class ImageDraw(object): if ink is not None: self.draw.draw_bitmap(xy, bitmap.im, ink) - def chord(self, xy, start, end, fill=None, outline=None): + def chord(self, xy, start, end, fill=None, outline=None, width=0): """Draw a chord.""" ink, fill = self._getink(outline, fill) if fill is not None: self.draw.draw_chord(xy, start, end, fill, 1) if ink is not None: - self.draw.draw_chord(xy, start, end, ink, 0) + self.draw.draw_chord(xy, start, end, ink, 0, width) - def ellipse(self, xy, fill=None, outline=None): + def ellipse(self, xy, fill=None, outline=None, width=0): """Draw an ellipse.""" ink, fill = self._getink(outline, fill) if fill is not None: self.draw.draw_ellipse(xy, fill, 1) if ink is not None: - self.draw.draw_ellipse(xy, ink, 0) + self.draw.draw_ellipse(xy, ink, 0, width) def line(self, xy, fill=None, width=0): """Draw a line, or a connected sequence of line segments.""" @@ -164,13 +164,13 @@ class ImageDraw(object): if ink is not None: self.draw.draw_outline(shape, ink, 0) - def pieslice(self, xy, start, end, fill=None, outline=None): + def pieslice(self, xy, start, end, fill=None, outline=None, width=0): """Draw a pieslice.""" ink, fill = self._getink(outline, fill) if fill is not None: self.draw.draw_pieslice(xy, start, end, fill, 1) if ink is not None: - self.draw.draw_pieslice(xy, start, end, ink, 0) + self.draw.draw_pieslice(xy, start, end, ink, 0, width) def point(self, xy, fill=None): """Draw one or more individual pixels.""" diff --git a/src/_imaging.c b/src/_imaging.c index 3cced9a0f..f1116a36c 100644 --- a/src/_imaging.c +++ b/src/_imaging.c @@ -2561,9 +2561,10 @@ _draw_arc(ImagingDrawObject* self, PyObject* args) PyObject* data; int ink; + int width = 0; float start, end; int op = 0; - if (!PyArg_ParseTuple(args, "Offi|i", &data, &start, &end, &ink)) + if (!PyArg_ParseTuple(args, "Offi|ii", &data, &start, &end, &ink, &width)) return NULL; n = PyPath_Flatten(data, &xy); @@ -2577,7 +2578,7 @@ _draw_arc(ImagingDrawObject* self, PyObject* args) n = ImagingDrawArc(self->image->image, (int) xy[0], (int) xy[1], (int) xy[2], (int) xy[3], - start, end, &ink, op + start, end, &ink, width, op ); free(xy); @@ -2633,9 +2634,10 @@ _draw_chord(ImagingDrawObject* self, PyObject* args) PyObject* data; int ink, fill; + int width = 0; float start, end; - if (!PyArg_ParseTuple(args, "Offii", - &data, &start, &end, &ink, &fill)) + if (!PyArg_ParseTuple(args, "Offii|i", + &data, &start, &end, &ink, &fill, &width)) return NULL; n = PyPath_Flatten(data, &xy); @@ -2649,7 +2651,7 @@ _draw_chord(ImagingDrawObject* self, PyObject* args) n = ImagingDrawChord(self->image->image, (int) xy[0], (int) xy[1], (int) xy[2], (int) xy[3], - start, end, &ink, fill, self->blend + start, end, &ink, fill, width, self->blend ); free(xy); @@ -2670,7 +2672,8 @@ _draw_ellipse(ImagingDrawObject* self, PyObject* args) PyObject* data; int ink; int fill = 0; - if (!PyArg_ParseTuple(args, "Oi|i", &data, &ink, &fill)) + int width = 0; + if (!PyArg_ParseTuple(args, "Oi|ii", &data, &ink, &fill, &width)) return NULL; n = PyPath_Flatten(data, &xy); @@ -2684,7 +2687,7 @@ _draw_ellipse(ImagingDrawObject* self, PyObject* args) n = ImagingDrawEllipse(self->image->image, (int) xy[0], (int) xy[1], (int) xy[2], (int) xy[3], - &ink, fill, self->blend + &ink, fill, width, self->blend ); free(xy); @@ -2850,8 +2853,9 @@ _draw_pieslice(ImagingDrawObject* self, PyObject* args) PyObject* data; int ink, fill; + int width = 0; float start, end; - if (!PyArg_ParseTuple(args, "Offii", &data, &start, &end, &ink, &fill)) + if (!PyArg_ParseTuple(args, "Offii|i", &data, &start, &end, &ink, &fill, &width)) return NULL; n = PyPath_Flatten(data, &xy); @@ -2865,7 +2869,7 @@ _draw_pieslice(ImagingDrawObject* self, PyObject* args) n = ImagingDrawPieslice(self->image->image, (int) xy[0], (int) xy[1], (int) xy[2], (int) xy[3], - start, end, &ink, fill, self->blend + start, end, &ink, fill, width, self->blend ); free(xy); diff --git a/src/libImaging/Draw.c b/src/libImaging/Draw.c index fee1cac63..37969af70 100644 --- a/src/libImaging/Draw.c +++ b/src/libImaging/Draw.c @@ -762,9 +762,10 @@ ellipsePoint(int cx, int cy, int w, int h, static int ellipse(Imaging im, int x0, int y0, int x1, int y1, float start, float end, const void* ink_, int fill, - int mode, int op) + int width, int mode, int op) { float i; + int j; int n; int cx, cy; int w, h; @@ -774,120 +775,131 @@ ellipse(Imaging im, int x0, int y0, int x1, int y1, DRAW* draw; INT32 ink; - w = x1 - x0; - h = y1 - y0; - if (w < 0 || h < 0) - return 0; - DRAWINIT(); - cx = (x0 + x1) / 2; - cy = (y0 + y1) / 2; - - while (end < start) - end += 360; - - if (end - start > 360) { - /* no need to go in loops */ - end = start + 361; + if (width == 0) { + width = 1; } - if (mode != ARC && fill) { + for (j = 0; j < width; j++) { - /* Build edge list */ - /* malloc check UNDONE, FLOAT? */ - Edge* e = calloc((end - start + 3), sizeof(Edge)); - if (!e) { - ImagingError_MemoryError(); - return -1; + w = x1 - x0; + h = y1 - y0; + if (w < 0 || h < 0) + return 0; + + cx = (x0 + x1) / 2; + cy = (y0 + y1) / 2; + + while (end < start) + end += 360; + + if (end - start > 360) { + /* no need to go in loops */ + end = start + 361; } - n = 0; + if (mode != ARC && fill) { - for (i = start; i < end+1; i++) { - if (i > end) { - i = end; + /* Build edge list */ + /* malloc check UNDONE, FLOAT? */ + Edge* e = calloc((end - start + 3), sizeof(Edge)); + if (!e) { + ImagingError_MemoryError(); + return -1; } - ellipsePoint(cx, cy, w, h, i, &x, &y); - if (i != start) - add_edge(&e[n++], lx, ly, x, y); - else - sx = x, sy = y; - lx = x, ly = y; - } + n = 0; - if (n > 0) { - /* close and draw polygon */ - if (mode == PIESLICE) { - if (x != cx || y != cy) { - add_edge(&e[n++], x, y, cx, cy); - add_edge(&e[n++], cx, cy, sx, sy); + for (i = start; i < end+1; i++) { + if (i > end) { + i = end; } - } else { - if (x != sx || y != sy) - add_edge(&e[n++], x, y, sx, sy); + ellipsePoint(cx, cy, w, h, i, &x, &y); + if (i != start) + add_edge(&e[n++], lx, ly, x, y); + else + sx = x, sy = y; + lx = x, ly = y; } - draw->polygon(im, n, e, ink, 0); - } - free(e); - - } else { - - for (i = start; i < end+1; i++) { - if (i > end) { - i = end; - } - ellipsePoint(cx, cy, w, h, i, &x, &y); - if (i != start) - draw->line(im, lx, ly, x, y, ink); - else - sx = x, sy = y; - lx = x, ly = y; - } - - if (i != start) { - if (mode == PIESLICE) { - if (x != cx || y != cy) { - draw->line(im, x, y, cx, cy, ink); - draw->line(im, cx, cy, sx, sy, ink); + if (n > 0) { + /* close and draw polygon */ + if (mode == PIESLICE) { + if (x != cx || y != cy) { + add_edge(&e[n++], x, y, cx, cy); + add_edge(&e[n++], cx, cy, sx, sy); + } + } else { + if (x != sx || y != sy) + add_edge(&e[n++], x, y, sx, sy); + } + draw->polygon(im, n, e, ink, 0); + } + + free(e); + + } else { + + for (i = start; i < end+1; i++) { + if (i > end) { + i = end; + } + ellipsePoint(cx, cy, w, h, i, &x, &y); + if (i != start) + draw->line(im, lx, ly, x, y, ink); + else + sx = x, sy = y; + lx = x, ly = y; + } + + if (i != start) { + if (mode == PIESLICE) { + if (x != cx || y != cy) { + draw->line(im, x, y, cx, cy, ink); + draw->line(im, cx, cy, sx, sy, ink); + } + } else if (mode == CHORD) { + if (x != sx || y != sy) + draw->line(im, x, y, sx, sy, ink); } - } else if (mode == CHORD) { - if (x != sx || y != sy) - draw->line(im, x, y, sx, sy, ink); } } + x0++; + y0++; + x1--; + y1--; } - return 0; } int ImagingDrawArc(Imaging im, int x0, int y0, int x1, int y1, - float start, float end, const void* ink, int op) + float start, float end, const void* ink, int width, int op) { - return ellipse(im, x0, y0, x1, y1, start, end, ink, 0, ARC, op); + return ellipse(im, x0, y0, x1, y1, start, end, ink, 0, width, ARC, op); } int ImagingDrawChord(Imaging im, int x0, int y0, int x1, int y1, - float start, float end, const void* ink, int fill, int op) + float start, float end, const void* ink, int fill, + int width, int op) { - return ellipse(im, x0, y0, x1, y1, start, end, ink, fill, CHORD, op); + return ellipse(im, x0, y0, x1, y1, start, end, ink, fill, width, CHORD, op); } int ImagingDrawEllipse(Imaging im, int x0, int y0, int x1, int y1, - const void* ink, int fill, int op) + const void* ink, int fill, int width, int op) { - return ellipse(im, x0, y0, x1, y1, 0, 360, ink, fill, CHORD, op); + return ellipse(im, x0, y0, x1, y1, 0, 360, ink, fill, width, CHORD, op); } int ImagingDrawPieslice(Imaging im, int x0, int y0, int x1, int y1, - float start, float end, const void* ink, int fill, int op) + float start, float end, const void* ink, int fill, + int width, int op) { - return ellipse(im, x0, y0, x1, y1, start, end, ink, fill, PIESLICE, op); + return ellipse(im, x0, y0, x1, y1, start, end, ink, fill, width, PIESLICE, op); } /* -------------------------------------------------------------------- */ diff --git a/src/libImaging/Imaging.h b/src/libImaging/Imaging.h index 4588602b1..e705e0a60 100644 --- a/src/libImaging/Imaging.h +++ b/src/libImaging/Imaging.h @@ -349,21 +349,22 @@ extern void ImagingCrack(Imaging im, int x0, int y0); /* Graphics */ extern int ImagingDrawArc(Imaging im, int x0, int y0, int x1, int y1, - float start, float end, const void* ink, int op); + float start, float end, const void* ink, int width, + int op); extern int ImagingDrawBitmap(Imaging im, int x0, int y0, Imaging bitmap, const void* ink, int op); extern int ImagingDrawChord(Imaging im, int x0, int y0, int x1, int y1, float start, float end, const void* ink, int fill, - int op); + int width, int op); extern int ImagingDrawEllipse(Imaging im, int x0, int y0, int x1, int y1, - const void* ink, int fill, int op); + const void* ink, int fill, int width, int op); extern int ImagingDrawLine(Imaging im, int x0, int y0, int x1, int y1, const void* ink, int op); extern int ImagingDrawWideLine(Imaging im, int x0, int y0, int x1, int y1, const void* ink, int width, int op); extern int ImagingDrawPieslice(Imaging im, int x0, int y0, int x1, int y1, float start, float end, const void* ink, int fill, - int op); + int width, int op); extern int ImagingDrawPoint(Imaging im, int x, int y, const void* ink, int op); extern int ImagingDrawPolygon(Imaging im, int points, int *xy, const void* ink, int fill, int op); From fbe5bdb6b605e06132d82b1347c9185299904a7c Mon Sep 17 00:00:00 2001 From: Hugo Date: Sat, 1 Sep 2018 14:40:36 +0300 Subject: [PATCH 3/6] Also apply width to pieslice's inner lines --- Tests/images/imagedraw_pieslice_width.png | Bin 488 -> 496 bytes Tests/images/imagedraw_pieslice_width_fill.png | Bin 500 -> 523 bytes docs/reference/ImageDraw.rst | 2 +- src/libImaging/Draw.c | 9 +++++++-- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Tests/images/imagedraw_pieslice_width.png b/Tests/images/imagedraw_pieslice_width.png index a83c4ab7b3469f0d2171148d31a4c7836311b50c..3bd69222cf3ff22977e358bcb0fcc2c84c98e284 100644 GIT binary patch delta 470 zcmV;{0V)3I1MmZoB!9O_L_t(|obB7&Zi6roMNy~9|Nk<1sDcQg2E$y=(7m2oDUHox zdwQuj%twkzTDmvpX>DzeGk>Sd}uG{bV#+GN~3mI~$MksrP=NPp_*YUj(pgDa4S!1})ttlHEUSY_DXs>7 zVO>c|ROB%1CsiOvr?9@usz4UIJi@wXQY~pUtSTU^(`6;MAex6IcZG($D{H8%)TcJ) ztO2%R-FXZ)=gLwaR-?p+p;oD?g(Y2#>0gEIS{7Gwl=@*UC4Z2zZOrhCmaWJlnrZjd4CeiqHI_z-=&cdpX;1u{{BNvFWGd%{9+Ui4|&})wN0r9vm53eR{YH3 z*rIt@YM)mu`;&Xtp;%l0Va_t+5mwfo$bIADR9W$PMQrizaq=%{TJ#HR^Tv8yRon@b z_-F98d4-3;bruq<>m+Sch#jOv-oV$_r~Q zDQn7UcqS?9G?T*mY%A*&PRa=Do=LT$yWy$?VNJA^=?yVFEYtH0k=Hdi zhsDNX&AK2Xtk2HZG*|jpaI((I&P#DUlEON?q; zHVH!VQWsyoqcV|NSy%xTvV=S^skN?Py7Vqtx?>Z(ueS7*~ z$j2P#x%%5v1Jz%@i{M`M>#?=!za=Lp{r+SU>Qv^e9nYA)=U0~E8~MF!vxLH)6qjU$ zwN3eXC${6~w{WR2t!q|R=N3=c@_&QGp_N?|UdK77uKUct(`?JC3%@YrzRHj lP2YNX%e3@WC^7S4=N|?GRln@au;X4J2~Sr)mvv4FO#ndA=xqQ1 delta 474 zcmV<00VV#61oQ)tB!9a}L_t(|obB4na)U4sL{X8-|Nk;sq)f#;1)1&{CHHK-KwKoS zgD%=GQUd$`L|rBga%l@8Iv zvkcEN&94uq$uX4QFbwdp)V%p*nwn)u52771RvNmv(&vj*FzL*?<&jA$M$1eH?vH=oZAx8Whn1u z-oQzC8b_{OV0#Et)yb~?=@JR{H5>H4>FkE_|FJyRX$RKBQkQmtdfjki;JNwnK! zI*XLwy|KxBr;xQt5Yo#%`1Bo>2i4NXoE~d&S*^}c0RR9100000008`7Ux?&SW9tNn QIRF3v07*qoM6N<$f&m`!LI3~& diff --git a/docs/reference/ImageDraw.rst b/docs/reference/ImageDraw.rst index 014075a0b..3bd460814 100644 --- a/docs/reference/ImageDraw.rst +++ b/docs/reference/ImageDraw.rst @@ -207,7 +207,7 @@ Methods :param end: Ending angle, in degrees. :param fill: Color to use for the fill. :param outline: Color to use for the outline. - :param width: The outer line width, in pixels. + :param width: The line width, in pixels. .. versionadded:: 5.2.0 diff --git a/src/libImaging/Draw.c b/src/libImaging/Draw.c index ea44e3605..eded23716 100644 --- a/src/libImaging/Draw.c +++ b/src/libImaging/Draw.c @@ -855,8 +855,13 @@ ellipse(Imaging im, int x0, int y0, int x1, int y1, if (i != start) { if (mode == PIESLICE) { if (x != cx || y != cy) { - draw->line(im, x, y, cx, cy, ink); - draw->line(im, cx, cy, sx, sy, ink); + if (width <= 1) { + draw->line(im, x, y, cx, cy, ink); + draw->line(im, cx, cy, sx, sy, ink); + } else { + ImagingDrawWideLine(im, x, y, cx, cy, &ink, width, op); + ImagingDrawWideLine(im, cx, cy, sx, sy, &ink, width, op); + } } } else if (mode == CHORD) { if (x != sx || y != sy) From 558e70d8cdd9045c46019752ba1198904079dac4 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 9 Sep 2018 13:57:01 +1000 Subject: [PATCH 4/6] Removed less than condition --- src/libImaging/Draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libImaging/Draw.c b/src/libImaging/Draw.c index eded23716..60650c373 100644 --- a/src/libImaging/Draw.c +++ b/src/libImaging/Draw.c @@ -855,7 +855,7 @@ ellipse(Imaging im, int x0, int y0, int x1, int y1, if (i != start) { if (mode == PIESLICE) { if (x != cx || y != cy) { - if (width <= 1) { + if (width == 1) { draw->line(im, x, y, cx, cy, ink); draw->line(im, cx, cy, sx, sy, ink); } else { From e266b033d1f528c32881b845d61b09fd9c954f27 Mon Sep 17 00:00:00 2001 From: Hugo Date: Sun, 16 Sep 2018 23:41:24 +0300 Subject: [PATCH 5/6] Update version added --- docs/reference/ImageDraw.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/reference/ImageDraw.rst b/docs/reference/ImageDraw.rst index 3bd460814..75ae30a32 100644 --- a/docs/reference/ImageDraw.rst +++ b/docs/reference/ImageDraw.rst @@ -140,7 +140,7 @@ Methods :param fill: Color to use for the arc. :param width: The line width, in pixels. - .. versionadded:: 5.2.0 + .. versionadded:: 5.3.0 .. py:method:: PIL.ImageDraw.ImageDraw.bitmap(xy, bitmap, fill=None) @@ -165,7 +165,7 @@ Methods :param fill: Color to use for the fill. :param width: The line width, in pixels. - .. versionadded:: 5.2.0 + .. versionadded:: 5.3.0 .. py:method:: PIL.ImageDraw.ImageDraw.ellipse(xy, fill=None, outline=None, width=0) @@ -178,7 +178,7 @@ Methods :param fill: Color to use for the fill. :param width: The line width, in pixels. - .. versionadded:: 5.2.0 + .. versionadded:: 5.3.0 .. py:method:: PIL.ImageDraw.ImageDraw.line(xy, fill=None, width=0) @@ -209,7 +209,7 @@ Methods :param outline: Color to use for the outline. :param width: The line width, in pixels. - .. versionadded:: 5.2.0 + .. versionadded:: 5.3.0 .. py:method:: PIL.ImageDraw.ImageDraw.point(xy, fill=None) @@ -243,7 +243,7 @@ Methods :param fill: Color to use for the fill. :param width: The line width, in pixels. - .. versionadded:: 5.2.0 + .. versionadded:: 5.3.0 .. py:method:: PIL.ImageDraw.ImageDraw.shape(shape, fill=None, outline=None) From d6d61b35dc2c867945bb3d9aa4d27400cde3a9f4 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 29 Sep 2018 21:44:25 +1000 Subject: [PATCH 6/6] Only draw pieslice's inner lines once --- src/libImaging/Draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libImaging/Draw.c b/src/libImaging/Draw.c index 60650c373..d0f374fe1 100644 --- a/src/libImaging/Draw.c +++ b/src/libImaging/Draw.c @@ -854,7 +854,7 @@ ellipse(Imaging im, int x0, int y0, int x1, int y1, if (i != start) { if (mode == PIESLICE) { - if (x != cx || y != cy) { + if (j == 0 && (x != cx || y != cy)) { if (width == 1) { draw->line(im, x, y, cx, cy, ink); draw->line(im, cx, cy, sx, sy, ink);