From deecd8a137c1481504fa48bcf41566e51eb5100a Mon Sep 17 00:00:00 2001 From: Terseus Date: Tue, 1 Apr 2014 13:01:03 +0200 Subject: [PATCH 01/22] Refactored polygon functions to unify logic The functions `polygon8`, `polygon32` and `polygon32rgba` all have exactly the same logic in code, only changes the hline function called inside. Now all the logic is contained in `polygon_generic` which gets a function pointer to the hline handler, so there is no duplicated code anymore. --- libImaging/Draw.c | 132 +++++++--------------------------------------- 1 file changed, 20 insertions(+), 112 deletions(-) diff --git a/libImaging/Draw.c b/libImaging/Draw.c index f13ba4df0..1241c8d3b 100644 --- a/libImaging/Draw.c +++ b/libImaging/Draw.c @@ -61,6 +61,9 @@ typedef struct { float dx; } Edge; +/* Type used in "polygon*" functions */ +typedef void (*hline_handler)(Imaging, int, int, int, int); + static inline void point8(Imaging im, int x, int y, int ink) { @@ -403,8 +406,10 @@ x_cmp(const void *x0, const void *x1) return 0; } + static inline int -polygon8(Imaging im, int n, Edge *e, int ink, int eofill) +polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, + hline_handler handler) { int i, j; float *xx; @@ -436,22 +441,23 @@ polygon8(Imaging im, int n, Edge *e, int ink, int eofill) for (;ymin <= ymax; ymin++) { y = ymin+0.5F; - for (i = j = 0; i < n; i++) + for (i = j = 0; i < n; i++) { if (y >= e[i].ymin && y <= e[i].ymax) { if (e[i].d == 0) - hline8(im, e[i].xmin, ymin, e[i].xmax, ink); + (*handler)(im, e[i].xmin, ymin, e[i].xmax, ink); else xx[j++] = (y-e[i].y0) * e[i].dx + e[i].x0; } + } if (j == 2) { if (xx[0] < xx[1]) - hline8(im, CEIL(xx[0]-0.5), ymin, FLOOR(xx[1]+0.5), ink); + (*handler)(im, CEIL(xx[0]-0.5), ymin, FLOOR(xx[1]+0.5), ink); else - hline8(im, CEIL(xx[1]-0.5), ymin, FLOOR(xx[0]+0.5), ink); + (*handler)(im, CEIL(xx[1]-0.5), ymin, FLOOR(xx[0]+0.5), ink); } else { qsort(xx, j, sizeof(float), x_cmp); for (i = 0; i < j-1 ; i += 2) - hline8(im, CEIL(xx[i]-0.5), ymin, FLOOR(xx[i+1]+0.5), ink); + (*handler)(im, CEIL(xx[i]-0.5), ymin, FLOOR(xx[i+1]+0.5), ink); } } @@ -460,120 +466,22 @@ polygon8(Imaging im, int n, Edge *e, int ink, int eofill) return 0; } +static inline int +polygon8(Imaging im, int n, Edge *e, int ink, int eofill) +{ + return polygon_generic(im, n, e, ink, eofill, hline8); +} + static inline int polygon32(Imaging im, int n, Edge *e, int ink, int eofill) { - int i, j; - float *xx; - int ymin, ymax; - float y; - - if (n <= 0) - return 0; - - /* Find upper and lower polygon boundary (within image) */ - - ymin = e[0].ymin; - ymax = e[0].ymax; - for (i = 1; i < n; i++) { - if (e[i].ymin < ymin) ymin = e[i].ymin; - if (e[i].ymax > ymax) ymax = e[i].ymax; - } - - if (ymin < 0) - ymin = 0; - if (ymax >= im->ysize) - ymax = im->ysize-1; - - /* Process polygon edges */ - - xx = malloc(n * sizeof(float)); - if (!xx) - return -1; - - for (;ymin <= ymax; ymin++) { - y = ymin+0.5F; - for (i = j = 0; i < n; i++) { - if (y >= e[i].ymin && y <= e[i].ymax) { - if (e[i].d == 0) - hline32(im, e[i].xmin, ymin, e[i].xmax, ink); - else - xx[j++] = (y-e[i].y0) * e[i].dx + e[i].x0; - } - } - if (j == 2) { - if (xx[0] < xx[1]) - hline32(im, CEIL(xx[0]-0.5), ymin, FLOOR(xx[1]+0.5), ink); - else - hline32(im, CEIL(xx[1]-0.5), ymin, FLOOR(xx[0]+0.5), ink); - } else { - qsort(xx, j, sizeof(float), x_cmp); - for (i = 0; i < j-1 ; i += 2) - hline32(im, CEIL(xx[i]-0.5), ymin, FLOOR(xx[i+1]+0.5), ink); - } - } - - free(xx); - - return 0; + return polygon_generic(im, n, e, ink, eofill, hline32); } static inline int polygon32rgba(Imaging im, int n, Edge *e, int ink, int eofill) { - int i, j; - float *xx; - int ymin, ymax; - float y; - - if (n <= 0) - return 0; - - /* Find upper and lower polygon boundary (within image) */ - - ymin = e[0].ymin; - ymax = e[0].ymax; - for (i = 1; i < n; i++) { - if (e[i].ymin < ymin) ymin = e[i].ymin; - if (e[i].ymax > ymax) ymax = e[i].ymax; - } - - if (ymin < 0) - ymin = 0; - if (ymax >= im->ysize) - ymax = im->ysize-1; - - /* Process polygon edges */ - - xx = malloc(n * sizeof(float)); - if (!xx) - return -1; - - for (;ymin <= ymax; ymin++) { - y = ymin+0.5F; - for (i = j = 0; i < n; i++) { - if (y >= e[i].ymin && y <= e[i].ymax) { - if (e[i].d == 0) - hline32rgba(im, e[i].xmin, ymin, e[i].xmax, ink); - else - xx[j++] = (y-e[i].y0) * e[i].dx + e[i].x0; - } - } - if (j == 2) { - if (xx[0] < xx[1]) - hline32rgba(im, CEIL(xx[0]-0.5), ymin, FLOOR(xx[1]+0.5), ink); - else - hline32rgba(im, CEIL(xx[1]-0.5), ymin, FLOOR(xx[0]+0.5), ink); - } else { - qsort(xx, j, sizeof(float), x_cmp); - for (i = 0; i < j-1 ; i += 2) - hline32rgba(im, CEIL(xx[i]-0.5), ymin, FLOOR(xx[i+1]+0.5), ink); - } - } - - free(xx); - - return 0; + return polygon_generic(im, n, e, ink, eofill, hline32rgba); } static inline void From 8739613cfb3731a1411de09c71161ef217ea2ca1 Mon Sep 17 00:00:00 2001 From: Terseus Date: Tue, 1 Apr 2014 13:08:15 +0200 Subject: [PATCH 02/22] Implementation of rounds around zero The rounds used in the library are towards positive/negative infinity. Since we're in a cartesian plane, rounds around zero are much more convenient, so we can use positive and negative values with consistent results. --- libImaging/Draw.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libImaging/Draw.c b/libImaging/Draw.c index 1241c8d3b..c29132112 100644 --- a/libImaging/Draw.c +++ b/libImaging/Draw.c @@ -49,6 +49,13 @@ #define BLEND(mask, in1, in2, tmp1, tmp2)\ (MULDIV255(in1, 255 - mask, tmp1) + MULDIV255(in2, mask, tmp2)) +/* + * Rounds around zero (up=torwards zero, down=away from zero) + * This guarantees that ROUND_UP|DOWN(f) == -ROUND_UP|DOWN(-f) + */ +#define ROUND_UP(f) ((int) ((f) >= 0.0 ? floor((f) + 0.5F) : -floor(fabs(f) + 0.5F))) +#define ROUND_DOWN(f) ((int) ((f) >= 0.0 ? ceil((f) - 0.5F) : -ceil(fabs(f) - 0.5F))) + /* -------------------------------------------------------------------- */ /* Primitives */ /* -------------------------------------------------------------------- */ From cd332fc38a2320207153b73d5fecedee135adb8b Mon Sep 17 00:00:00 2001 From: Terseus Date: Wed, 2 Apr 2014 20:29:56 +0200 Subject: [PATCH 03/22] Rewrite of the polygon_generic function The (previously refactored) polygon_generic function didn't draw consistent polygons (equilateral polygons were not equilateral nor symmetrical). The most notable changes are: * The horizontal edges are searched for when finding the polygon boundaries, drawn and discarded from the edge list used to detect intersections. * The intersections are now checked and calculated from the current value of the scan line (ymin) instead of in the middle (ymin + 0.5). * Because the change in the scan line behavior, we should duplicate the intersections in the maximum Y value of an edge or there will be draw errors with concave and complex polygons. * The rounds of the X coordinates in the hline function calls are switched to draw the inner pixels. * Removed the ugly micro-optimization of qsort at the end. This implementation of the scan line algorithm may not be technically correct, it's not optimized and it have problems with some edge cases, like a wide line from (x0, y) to (x1, y + 1), therefore it should be reviewed in the future. --- libImaging/Draw.c | 93 ++++++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/libImaging/Draw.c b/libImaging/Draw.c index c29132112..3d3ecc2a2 100644 --- a/libImaging/Draw.c +++ b/libImaging/Draw.c @@ -414,62 +414,71 @@ x_cmp(const void *x0, const void *x1) } +/* + * Filled polygon draw function using scan line algorithm. + */ static inline int polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, - hline_handler handler) + hline_handler hline) { - int i, j; - float *xx; - int ymin, ymax; - float y; - - if (n <= 0) + if (n <= 0) { return 0; - - /* Find upper and lower polygon boundary (within image) */ - - ymin = e[0].ymin; - ymax = e[0].ymax; - for (i = 1; i < n; i++) { - if (e[i].ymin < ymin) ymin = e[i].ymin; - if (e[i].ymax > ymax) ymax = e[i].ymax; } - if (ymin < 0) - ymin = 0; - if (ymax >= im->ysize) - ymax = im->ysize-1; - - /* Process polygon edges */ - - xx = malloc(n * sizeof(float)); - if (!xx) + /* Initialize the edge table and find polygon boundaries */ + Edge** edge_table = malloc(sizeof(Edge*) * n); + if (!edge_table) { return -1; + } + int edge_count = 0; + int ymin = im->ysize - 1; + int ymax = 0; + int i; + for (i = 0; i < n; i++) { + /* This causes that the pixels of horizontal edges are drawn twice :( + * but without it there are inconsistencies in ellipses */ + if (e[i].ymin == e[i].ymax) { + (*hline)(im, e[i].xmin, e[i].ymin, e[i].xmax, ink); + continue; + } + if (ymin > e[i].ymin) { + ymin = e[i].ymin; + } + if (ymax < e[i].ymax) { + ymax = e[i].ymax; + } + edge_table[edge_count++] = (e + i); + } + if (ymin < 0) { + ymin = 0; + } + if (ymax >= im->ysize) { + ymax = im->ysize - 1; + } - for (;ymin <= ymax; ymin++) { - y = ymin+0.5F; - for (i = j = 0; i < n; i++) { - if (y >= e[i].ymin && y <= e[i].ymax) { - if (e[i].d == 0) - (*handler)(im, e[i].xmin, ymin, e[i].xmax, ink); - else - xx[j++] = (y-e[i].y0) * e[i].dx + e[i].x0; + /* Process the edge table with a scan line searching for intersections */ + float* xx = malloc(sizeof(float) * edge_count * 2); + for (; ymin <= ymax; ymin++) { + int j = 0; + for (i = 0; i < edge_count; i++) { + Edge* current = edge_table[i]; + if (ymin >= current->ymin && ymin <= current->ymax) { + xx[j++] = (ymin - current->y0) * current->dx + current->x0; + } + /* Needed to draw consistent polygons */ + if (ymin == current->ymax && ymin < ymax) { + xx[j] = xx[j - 1]; + j++; } } - if (j == 2) { - if (xx[0] < xx[1]) - (*handler)(im, CEIL(xx[0]-0.5), ymin, FLOOR(xx[1]+0.5), ink); - else - (*handler)(im, CEIL(xx[1]-0.5), ymin, FLOOR(xx[0]+0.5), ink); - } else { - qsort(xx, j, sizeof(float), x_cmp); - for (i = 0; i < j-1 ; i += 2) - (*handler)(im, CEIL(xx[i]-0.5), ymin, FLOOR(xx[i+1]+0.5), ink); + qsort(xx, j, sizeof(float), x_cmp); + for (i = 1; i < j; i += 2) { + (*hline)(im, ROUND_UP(xx[i - 1]), ymin, ROUND_DOWN(xx[i]), ink); } } free(xx); - + free(edge_table); return 0; } From be09da65078d1368c27354e4c4f1cf7611cfa2e6 Mon Sep 17 00:00:00 2001 From: Terseus Date: Wed, 2 Apr 2014 21:30:42 +0200 Subject: [PATCH 04/22] Rewrite of the ImagingDrawWideLine function The previous version of the function didn't generate correct wide lines of even width. The most notable changes are: * Make variable names far more descriptive about the process. * Corrected the width calculation; we should deduct one pixel from the width because the pixels at the center of the line doesn't count for the triangles. * Now we calculate *two* ratios, one for left/top displacement (dxmin) and one for right/bottom (dxmax), this fix the behavior with lines of even width. It can probably be optimized. --- libImaging/Draw.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/libImaging/Draw.c b/libImaging/Draw.c index 3d3ecc2a2..a0430652a 100644 --- a/libImaging/Draw.c +++ b/libImaging/Draw.c @@ -588,11 +588,6 @@ ImagingDrawWideLine(Imaging im, int x0, int y0, int x1, int y1, DRAW* draw; INT32 ink; - Edge e[4]; - - int dx, dy; - double d; - DRAWINIT(); if (width <= 1) { @@ -600,23 +595,34 @@ ImagingDrawWideLine(Imaging im, int x0, int y0, int x1, int y1, return 0; } - dx = x1-x0; - dy = y1-y0; - + int dx = x1-x0; + int dy = y1-y0; if (dx == 0 && dy == 0) { draw->point(im, x0, y0, ink); return 0; } - d = width / sqrt((float) (dx*dx + dy*dy)) / 2.0; + double big_hypotenuse = sqrt((double) (dx*dx + dy*dy)); + double small_hypotenuse = (width - 1) / 2.0; + double ratio_max = ROUND_UP(small_hypotenuse) / big_hypotenuse; + double ratio_min = ROUND_DOWN(small_hypotenuse) / big_hypotenuse; - dx = (int) floor(d * (y1-y0) + 0.5); - dy = (int) floor(d * (x1-x0) + 0.5); + int dxmin = ROUND_DOWN(ratio_min * dy); + int dxmax = ROUND_DOWN(ratio_max * dy); + int dymin = ROUND_DOWN(ratio_min * dx); + int dymax = ROUND_DOWN(ratio_max * dx); + int vertices[4][2] = { + {x0 - dxmin, y0 + dymax}, + {x1 - dxmin, y1 + dymax}, + {x1 + dxmax, y1 - dymin}, + {x0 + dxmax, y0 - dymin} + }; - add_edge(e+0, x0 - dx, y0 + dy, x1 - dx, y1 + dy); - add_edge(e+1, x1 - dx, y1 + dy, x1 + dx, y1 - dy); - add_edge(e+2, x1 + dx, y1 - dy, x0 + dx, y0 - dy); - add_edge(e+3, x0 + dx, y0 - dy, x0 - dx, y0 + dy); + Edge e[4]; + add_edge(e+0, vertices[0][0], vertices[0][1], vertices[1][0], vertices[1][1]); + add_edge(e+1, vertices[1][0], vertices[1][1], vertices[2][0], vertices[2][1]); + add_edge(e+2, vertices[2][0], vertices[2][1], vertices[3][0], vertices[3][1]); + add_edge(e+3, vertices[3][0], vertices[3][1], vertices[0][0], vertices[0][1]); draw->polygon(im, 4, e, ink, 0); From dbe3db6fc541e15b7f54c4a1fddf1ceb384de2d2 Mon Sep 17 00:00:00 2001 From: Terseus Date: Thu, 3 Apr 2014 11:15:21 +0200 Subject: [PATCH 05/22] Oops, fixed typo in comments --- libImaging/Draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libImaging/Draw.c b/libImaging/Draw.c index a0430652a..43fe32450 100644 --- a/libImaging/Draw.c +++ b/libImaging/Draw.c @@ -50,7 +50,7 @@ (MULDIV255(in1, 255 - mask, tmp1) + MULDIV255(in2, mask, tmp2)) /* - * Rounds around zero (up=torwards zero, down=away from zero) + * Rounds around zero (up=away from zero, down=torwards zero) * This guarantees that ROUND_UP|DOWN(f) == -ROUND_UP|DOWN(-f) */ #define ROUND_UP(f) ((int) ((f) >= 0.0 ? floor((f) + 0.5F) : -floor(fabs(f) + 0.5F))) From 7de14a51dda40f46711f8c20c6ddce6a8bac7713 Mon Sep 17 00:00:00 2001 From: Terseus Date: Fri, 4 Apr 2014 10:27:08 +0200 Subject: [PATCH 06/22] Added base method and constants to test_imagedraw The method `create_base_image_draw` will be used in all the new draw tests. --- Tests/test_imagedraw.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index f8b5c3c5c..ab09d7174 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -2,6 +2,13 @@ from tester import * from PIL import Image from PIL import ImageDraw +import os.path + +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +GRAY = (190, 190, 190) +DEFAULT_MODE = 'RGB' +IMAGES_PATH = os.path.join('Tests', 'images', 'imagedraw') def test_sanity(): @@ -26,3 +33,12 @@ def test_deprecated(): assert_warning(DeprecationWarning, lambda: draw.setink(0)) assert_warning(DeprecationWarning, lambda: draw.setfill(0)) + +def create_base_image_draw(size, mode=DEFAULT_MODE, background1=WHITE, background2=GRAY): + img = Image.new(mode, size, background1) + for x in range(0, size[0]): + for y in range(0, size[1]): + if (x + y) % 2 == 0: + img.putpixel((x, y), background2) + return (img, ImageDraw.Draw(img)) + From ec74779b198c26dbf82e42644476e35bd2044850 Mon Sep 17 00:00:00 2001 From: Terseus Date: Fri, 4 Apr 2014 11:28:41 +0200 Subject: [PATCH 07/22] Added test for a simple square --- Tests/images/imagedraw/square.png | Bin 0 -> 135 bytes Tests/test_imagedraw.py | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 Tests/images/imagedraw/square.png diff --git a/Tests/images/imagedraw/square.png b/Tests/images/imagedraw/square.png new file mode 100644 index 0000000000000000000000000000000000000000..842ee4722d52f6a93a4557286ce8412a9d4e0e7d GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V6Od#Ih`sfJr))YWBHdw_eFt1YMw5RArhC9Z*0%M|NsC0!ihW;PrkjqeVie*l`)_s*^6K5 dZptrd27!ai9^Q>R`wXaq!PC{xWt~$(69E6ZC-wjU literal 0 HcmV?d00001 diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index ab09d7174..138c14cca 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -42,3 +42,24 @@ def create_base_image_draw(size, mode=DEFAULT_MODE, background1=WHITE, backgroun img.putpixel((x, y), background2) return (img, ImageDraw.Draw(img)) + +def test_square(): + expected = Image.open(os.path.join(IMAGES_PATH, 'square.png')) + expected.load() + # Normal polygon + img, draw = create_base_image_draw((10, 10)) + draw.polygon([(2, 2), (2, 7), (7, 7), (7, 2)], BLACK) + assert_image_equal(img, expected) + # Inverted polygon + img, draw = create_base_image_draw((10, 10)) + draw.polygon([(7, 7), (7, 2), (2, 2), (2, 7)], BLACK) + assert_image_equal(img, expected) + # Normal rectangle + img, draw = create_base_image_draw((10, 10)) + draw.rectangle((2, 2, 7, 7), BLACK) + assert_image_equal(img, expected) + # Inverted rectangle + img, draw = create_base_image_draw((10, 10)) + draw.rectangle((7, 7, 2, 2), BLACK) + assert_image_equal(img, expected) + From e2cb2195eb3bc90c1f3bc47a375802d8416f804a Mon Sep 17 00:00:00 2001 From: Terseus Date: Fri, 4 Apr 2014 11:46:58 +0200 Subject: [PATCH 08/22] Added test for a simple right triangle The diagonals of the right angled edges must be perfect and the bottom vertice should be drawn. --- Tests/images/imagedraw/triangle_right.png | Bin 0 -> 168 bytes Tests/test_imagedraw.py | 7 +++++++ 2 files changed, 7 insertions(+) create mode 100644 Tests/images/imagedraw/triangle_right.png diff --git a/Tests/images/imagedraw/triangle_right.png b/Tests/images/imagedraw/triangle_right.png new file mode 100644 index 0000000000000000000000000000000000000000..e91fa580234157bcbe1784671e6b3a89d36f7fef GIT binary patch literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1SFYWcSQjy&H|6fVg?3oVGw3ym^DWND9B#o z>FdgVkA;O(OXD=}PE(+eyQhm|h{fsT8{6~m|NsC0q_X6RYdiDr+qEssGiKIg=sv6R z^2np~N2N*MjVD?awwW1PeQY&zoXhe^a=+i9k3H_sJN$1upGsrkyqq5t@`6nTXe5KD LtDnm{r-UW|g`qaL literal 0 HcmV?d00001 diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index 138c14cca..45f9d5f03 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -63,3 +63,10 @@ def test_square(): draw.rectangle((7, 7, 2, 2), BLACK) assert_image_equal(img, expected) + +def test_triangle_right(): + expected = Image.open(os.path.join(IMAGES_PATH, 'triangle_right.png')) + expected.load() + img, draw = create_base_image_draw((20, 20)) + draw.polygon([(3, 5), (17, 5), (10, 12)], BLACK) + assert_image_equal(img, expected) From fee2faa8dc7e5c552bd389e399956b7abf9bde4f Mon Sep 17 00:00:00 2001 From: Terseus Date: Fri, 4 Apr 2014 12:35:26 +0200 Subject: [PATCH 09/22] Added test for horizontal lines Notice that the expansion of the line width depends on the order of the points: * If the bigger axis value is provided as the *second* point the line expand first to the *positive* side of the axis. * If the bigger axis value is provided as the *first* point the line expand first to the *negative* side of the axis. * If the line's width is odd this doesn't matter, as the line will expand the same amount to both sides. This behavior should be consistent in both horizontal and vertical lines. --- .../line_horizontal_w2px_inverted.png | Bin 0 -> 143 bytes .../imagedraw/line_horizontal_w2px_normal.png | Bin 0 -> 141 bytes .../images/imagedraw/line_horizontal_w3px.png | Bin 0 -> 145 bytes Tests/test_imagedraw.py | 25 ++++++++++++++++++ 4 files changed, 25 insertions(+) create mode 100644 Tests/images/imagedraw/line_horizontal_w2px_inverted.png create mode 100644 Tests/images/imagedraw/line_horizontal_w2px_normal.png create mode 100644 Tests/images/imagedraw/line_horizontal_w3px.png diff --git a/Tests/images/imagedraw/line_horizontal_w2px_inverted.png b/Tests/images/imagedraw/line_horizontal_w2px_inverted.png new file mode 100644 index 0000000000000000000000000000000000000000..a2bb3bbabe8681bda838121298492ec0fa0ec7d4 GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1SFYWcSQjy&H|6fVg?3oVGw3ym^DWND9B#o z>FdgVkA;Pclf$Pc;3!Z?&(p;*#Nu@FjqUmO|NsAgQd#oEwVnC*?b;lZjhW*d4y65= l#lCjFd#>Ep${ja&7^0@%XP8{HC?2Sj!PC{xWt~$(697S^DlGs2 literal 0 HcmV?d00001 diff --git a/Tests/images/imagedraw/line_horizontal_w2px_normal.png b/Tests/images/imagedraw/line_horizontal_w2px_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d409ea48aa491f96ca5e7df6b95d10bb08a255 GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1SFYWcSQjy&H|6fVg?3oVGw3ym^DWND9B#o z>FdgVkA;Pc!;ovz%O0SRj;D)bh{fsT8{6~m|NsC0q_X6RYdiDr+qFGRG-i%-IFR;d jmb-KHm1lvoIVUrmh`i6R!7BRFdgVkA;O(nKNvekP=YHz|+Ms#Nu@FjqUmO|NsAgQd#oEwVnC*?b;lZjhW*d4y65= nm6`cjfcI_SZ1>z{>&`OdUpw;lGq3h@pk4+~S3j3^P6 Date: Fri, 4 Apr 2014 12:45:47 +0200 Subject: [PATCH 10/22] Added test for vertical lines. The behavior is consistent with horizontal lines, see previous commit for details. --- .../imagedraw/line_vertical_w2px_inverted.png | Bin 0 -> 145 bytes .../imagedraw/line_vertical_w2px_normal.png | Bin 0 -> 144 bytes Tests/images/imagedraw/line_vertical_w3px.png | Bin 0 -> 142 bytes Tests/test_imagedraw.py | 25 ++++++++++++++++++ 4 files changed, 25 insertions(+) create mode 100644 Tests/images/imagedraw/line_vertical_w2px_inverted.png create mode 100644 Tests/images/imagedraw/line_vertical_w2px_normal.png create mode 100644 Tests/images/imagedraw/line_vertical_w3px.png diff --git a/Tests/images/imagedraw/line_vertical_w2px_inverted.png b/Tests/images/imagedraw/line_vertical_w2px_inverted.png new file mode 100644 index 0000000000000000000000000000000000000000..74d666b885efa5adfdb95a9bc58da19afff46b38 GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1SFYWcSQjy&H|6fVg?3oVGw3ym^DWND9B#o z>FdgVkA;PcSH0PA#SEa3fv1aOh{fsT8{6~m|NsC0q_X6RYdiDr+qESo7&C*xOfzSb j{#!O#pEK4iI+4auC~==*SFdgVkA;Pc$Gm-R=U$+YzNd?0h{fr*mlp~$I0zg%@FhMZ>hY2ChCc@%7_D~jy`)>Z m@>4qx!_q&GPEP*5D$b5~=6weL$V+BGtqh*7elF{r5}E*%{45p# literal 0 HcmV?d00001 diff --git a/Tests/images/imagedraw/line_vertical_w3px.png b/Tests/images/imagedraw/line_vertical_w3px.png new file mode 100644 index 0000000000000000000000000000000000000000..4e5234f2a8a9a66a2a13bfc12c56723c5e3a4883 GIT binary patch literal 142 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1SFYWcSQjy&H|6fVg?3oVGw3ym^DWND9B#o z>FdgVkA;O(#c0Kw+=D Date: Fri, 4 Apr 2014 14:02:36 +0200 Subject: [PATCH 11/22] Added missing xx pointer check --- libImaging/Draw.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libImaging/Draw.c b/libImaging/Draw.c index 43fe32450..8daf0e2c0 100644 --- a/libImaging/Draw.c +++ b/libImaging/Draw.c @@ -458,6 +458,9 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, /* Process the edge table with a scan line searching for intersections */ float* xx = malloc(sizeof(float) * edge_count * 2); + if (!xx) { + return -1; + } for (; ymin <= ymax; ymin++) { int j = 0; for (i = 0; i < edge_count; i++) { From 2f6a4d5f1a693bf69a04032dd43dc550a7de2230 Mon Sep 17 00:00:00 2001 From: Terseus Date: Fri, 4 Apr 2014 18:57:08 +0200 Subject: [PATCH 12/22] Added missing free when xx fail --- libImaging/Draw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libImaging/Draw.c b/libImaging/Draw.c index 8daf0e2c0..ad8d589af 100644 --- a/libImaging/Draw.c +++ b/libImaging/Draw.c @@ -459,6 +459,7 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, /* Process the edge table with a scan line searching for intersections */ float* xx = malloc(sizeof(float) * edge_count * 2); if (!xx) { + free(edge_table) return -1; } for (; ymin <= ymax; ymin++) { From 8eae39e98ff72c561d78c40362c6a6d39e77ac3b Mon Sep 17 00:00:00 2001 From: Terseus Date: Fri, 4 Apr 2014 19:20:29 +0200 Subject: [PATCH 13/22] Oops, added missing ';' Now writing in the wall "don't push before compile" 100 times. --- libImaging/Draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libImaging/Draw.c b/libImaging/Draw.c index ad8d589af..2f53fde79 100644 --- a/libImaging/Draw.c +++ b/libImaging/Draw.c @@ -459,7 +459,7 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, /* Process the edge table with a scan line searching for intersections */ float* xx = malloc(sizeof(float) * edge_count * 2); if (!xx) { - free(edge_table) + free(edge_table); return -1; } for (; ymin <= ymax; ymin++) { From 92dd58c01464d74dcfea7a092a80da5cdfd1667c Mon Sep 17 00:00:00 2001 From: Terseus Date: Sun, 6 Apr 2014 13:57:34 +0200 Subject: [PATCH 14/22] Added descriptive errors to imagedraw tests --- Tests/test_imagedraw.py | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index e42a2f054..ddf2fd68f 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -46,22 +46,18 @@ def create_base_image_draw(size, mode=DEFAULT_MODE, background1=WHITE, backgroun def test_square(): expected = Image.open(os.path.join(IMAGES_PATH, 'square.png')) expected.load() - # Normal polygon img, draw = create_base_image_draw((10, 10)) draw.polygon([(2, 2), (2, 7), (7, 7), (7, 2)], BLACK) - assert_image_equal(img, expected) - # Inverted polygon + assert_image_equal(img, expected, 'square as normal polygon failed') img, draw = create_base_image_draw((10, 10)) draw.polygon([(7, 7), (7, 2), (2, 2), (2, 7)], BLACK) - assert_image_equal(img, expected) - # Normal rectangle + assert_image_equal(img, expected, 'square as inverted polygon failed') img, draw = create_base_image_draw((10, 10)) draw.rectangle((2, 2, 7, 7), BLACK) - assert_image_equal(img, expected) - # Inverted rectangle + assert_image_equal(img, expected, 'square as normal rectangle failed') img, draw = create_base_image_draw((10, 10)) draw.rectangle((7, 7, 2, 2), BLACK) - assert_image_equal(img, expected) + assert_image_equal(img, expected, 'square as inverted rectangle failed') def test_triangle_right(): @@ -69,54 +65,46 @@ def test_triangle_right(): expected.load() img, draw = create_base_image_draw((20, 20)) draw.polygon([(3, 5), (17, 5), (10, 12)], BLACK) - assert_image_equal(img, expected) + assert_image_equal(img, expected, 'triangle right failed') def test_line_horizontal(): - # Normal 2px line expected = Image.open(os.path.join(IMAGES_PATH, 'line_horizontal_w2px_normal.png')) expected.load() img, draw = create_base_image_draw((20, 20)) draw.line((5, 5, 14, 5), BLACK, 2) - assert_image_equal(img, expected) - # Inverted 2px line + assert_image_equal(img, expected, 'line straigth horizontal normal 2px wide failed') expected = Image.open(os.path.join(IMAGES_PATH, 'line_horizontal_w2px_inverted.png')) expected.load() img, draw = create_base_image_draw((20, 20)) draw.line((14, 5, 5, 5), BLACK, 2) - assert_image_equal(img, expected) - # Normal 3px line + assert_image_equal(img, expected, 'line straigth horizontal inverted 2px wide failed') expected = Image.open(os.path.join(IMAGES_PATH, 'line_horizontal_w3px.png')) expected.load() img, draw = create_base_image_draw((20, 20)) draw.line((5, 5, 14, 5), BLACK, 3) - assert_image_equal(img, expected) - # Inverted 3px line + assert_image_equal(img, expected, 'line straigth horizontal normal 3px wide failed') img, draw = create_base_image_draw((20, 20)) draw.line((14, 5, 5, 5), BLACK, 3) - assert_image_equal(img, expected) + assert_image_equal(img, expected, 'line straigth horizontal inverted 3px wide failed') def test_line_vertical(): - # Normal 2px line expected = Image.open(os.path.join(IMAGES_PATH, 'line_vertical_w2px_normal.png')) expected.load() img, draw = create_base_image_draw((20, 20)) draw.line((5, 5, 5, 14), BLACK, 2) - assert_image_equal(img, expected) - # Inverted 2px line + assert_image_equal(img, expected, 'line straigth vertical normal 2px wide failed') expected = Image.open(os.path.join(IMAGES_PATH, 'line_vertical_w2px_inverted.png')) expected.load() img, draw = create_base_image_draw((20, 20)) draw.line((5, 14, 5, 5), BLACK, 2) - assert_image_equal(img, expected) - # Normal 3px line + assert_image_equal(img, expected, 'line straigth vertical inverted 2px wide failed') expected = Image.open(os.path.join(IMAGES_PATH, 'line_vertical_w3px.png')) expected.load() img, draw = create_base_image_draw((20, 20)) draw.line((5, 5, 5, 14), BLACK, 3) - assert_image_equal(img, expected) - # Inverted 3px line + assert_image_equal(img, expected, 'line straigth vertical normal 3px wide failed') img, draw = create_base_image_draw((20, 20)) draw.line((5, 14, 5, 5), BLACK, 3) - assert_image_equal(img, expected) + assert_image_equal(img, expected, 'line straigth vertical inverted 3px wide failed') From 8228caf14daf94c5bd970edcc9344fa076184075 Mon Sep 17 00:00:00 2001 From: Terseus Date: Wed, 9 Apr 2014 17:39:52 +0200 Subject: [PATCH 15/22] =?UTF-8?q?Added=20some=20oblique=2045=C2=BA=20lines?= =?UTF-8?q?=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only the oblique 3 pixels wide lines are defined: * The oblique 2 pixels wide lines are somewhat hard to define. * To define the oblique lines wider than 3 pixels we neet to define first how the oblique lines should expand their width (realistic or exact). --- .../imagedraw/line_oblique_45_w3px_a.png | Bin 0 -> 182 bytes .../imagedraw/line_oblique_45_w3px_b.png | Bin 0 -> 179 bytes Tests/test_imagedraw.py | 19 ++++++++++++++++++ 3 files changed, 19 insertions(+) create mode 100644 Tests/images/imagedraw/line_oblique_45_w3px_a.png create mode 100644 Tests/images/imagedraw/line_oblique_45_w3px_b.png diff --git a/Tests/images/imagedraw/line_oblique_45_w3px_a.png b/Tests/images/imagedraw/line_oblique_45_w3px_a.png new file mode 100644 index 0000000000000000000000000000000000000000..55c535e29c7970fedfaf710ca1a8cc67efcf47ce GIT binary patch literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1SFYWcSQjy&H|6fVg?3oVGw3ym^DWND9B#o z>FdgVkA;(8nm=yu`evX|sHcl#h{frrlMVR}7;rGZ|KI=V`iUtEgA~>+_exFZ^mA`< z3<^!1J7da`>1P}=(ynJ4pFee$um0cWlk@NU?7O@9aDVXKAKr)3?%i-dAAR%OS?9E$ b4{i06g=S3gTe~DWM4fJi9@C literal 0 HcmV?d00001 diff --git a/Tests/images/imagedraw/line_oblique_45_w3px_b.png b/Tests/images/imagedraw/line_oblique_45_w3px_b.png new file mode 100644 index 0000000000000000000000000000000000000000..8c1036559cc72b285623cfbcb7559d64c5c7801e GIT binary patch literal 179 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1SFYWcSQjy&H|6fVg?3oVGw3ym^DWND9B#o z>FdgVkA;(8#q#7$0X3jdkf)1dh{frvm#u{u6gZp@-uWM}Qz}f%>V$goLXndEZHyC4 zjB}m!JRem`HfSXKMIW=`wbT%{)Kj+9?JrvT Date: Wed, 9 Apr 2014 19:05:31 +0200 Subject: [PATCH 16/22] Added tests of hor/ver lines 101px wide These tests should guarantee that the proportion of the width is maintained with a margin of error < 1%. --- Tests/images/imagedraw/line_horizontal_w101px.png | Bin 0 -> 368 bytes Tests/images/imagedraw/line_vertical_w101px.png | Bin 0 -> 438 bytes Tests/test_imagedraw.py | 10 ++++++++++ 3 files changed, 10 insertions(+) create mode 100644 Tests/images/imagedraw/line_horizontal_w101px.png create mode 100644 Tests/images/imagedraw/line_vertical_w101px.png diff --git a/Tests/images/imagedraw/line_horizontal_w101px.png b/Tests/images/imagedraw/line_horizontal_w101px.png new file mode 100644 index 0000000000000000000000000000000000000000..bbcc8133fd3975eb00d5625a97e3df0ed176ca9a GIT binary patch literal 368 zcmeAS@N?(olHy`uVBq!ia0vp^CxAGQg9%8!tv_uAq&N#aB8wRqxP?KOkzv*x37{Z* ziKnkC`#ly;K?e5sFOmWo7#R6IT^vIyZoR#-ke9)L!`1PdeAm?#>sDqsOt{lIKS5C6 zX!EKyZ|{C!wchxUJ8a{cq{ySY@_u~Pn)d#K@5TTf5$>ZwAi`-Qmb22ChI3N5He`VXYGKC+O9OtZ;G#IR0 z^={j9Y5hC5DjL1C{s&5~H3@z>cj<~Hlf1NCRi}mod4dQ{t(71F5D^F#01;gf0ib9Q zR2fio5lEQ`TnjO(!6t*WKum_%4Ym*L0Fd1f3&3U*Pz^Q%w{t-Tk?FagE4+5^{dj2Y e(n+VjmoZG2pILd>QkD}K<_w;$elF{r5}E*{Dxzxu literal 0 HcmV?d00001 diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index defb3805a..46bb43a11 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -87,6 +87,11 @@ def test_line_horizontal(): img, draw = create_base_image_draw((20, 20)) draw.line((14, 5, 5, 5), BLACK, 3) assert_image_equal(img, expected, 'line straigth horizontal inverted 3px wide failed') + expected = Image.open(os.path.join(IMAGES_PATH, 'line_horizontal_w101px.png')) + expected.load() + img, draw = create_base_image_draw((200, 110)) + draw.line((5, 55, 195, 55), BLACK, 101) + assert_image_equal(img, expected, 'line straigth horizontal 101px wide failed') def test_line_vertical(): @@ -108,6 +113,11 @@ def test_line_vertical(): img, draw = create_base_image_draw((20, 20)) draw.line((5, 14, 5, 5), BLACK, 3) assert_image_equal(img, expected, 'line straigth vertical inverted 3px wide failed') + expected = Image.open(os.path.join(IMAGES_PATH, 'line_vertical_w101px.png')) + expected.load() + img, draw = create_base_image_draw((110, 200)) + draw.line((55, 5, 55, 195), BLACK, 101) + assert_image_equal(img, expected, 'line straigth vertical 101px wide failed') def test_line_oblique_45(): From b987d90568ec3662c0c05085412b2f2b4a1c519f Mon Sep 17 00:00:00 2001 From: Terseus Date: Wed, 9 Apr 2014 19:12:03 +0200 Subject: [PATCH 17/22] Added tests for lines with 1px slope This tests are designed to guarantee that the wide lines behave exactly like normal lines drawn with the Bresenham's algorithm. This tests are somewhat subjective since this is non-defined behavior, but I think that mimic the Bresenham's algorithm is reliable enough. Currently the horizontal version of this test **fail**. --- .../imagedraw/line_horizontal_slope1px_w2px.png | Bin 0 -> 147 bytes .../imagedraw/line_vertical_slope1px_w2px.png | Bin 0 -> 153 bytes Tests/test_imagedraw.py | 10 ++++++++++ 3 files changed, 10 insertions(+) create mode 100644 Tests/images/imagedraw/line_horizontal_slope1px_w2px.png create mode 100644 Tests/images/imagedraw/line_vertical_slope1px_w2px.png diff --git a/Tests/images/imagedraw/line_horizontal_slope1px_w2px.png b/Tests/images/imagedraw/line_horizontal_slope1px_w2px.png new file mode 100644 index 0000000000000000000000000000000000000000..aaed7678680d7e413d23532b97d391a3611e53b9 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1SFYWcSQjy&H|6fVg?3oVGw3ym^DWND9B#o z>FdgVkA+h}LUew|!*ZaIk*AAeh{fsT8{6~m|NsC0q_X6RYdiDr+qFGRG-lRPIGe_{ pr@_R2ai-k7g|=CrSDcklVbDErpTW3kSprZugQu&X%Q~loCIB4yE7kx2 literal 0 HcmV?d00001 diff --git a/Tests/images/imagedraw/line_vertical_slope1px_w2px.png b/Tests/images/imagedraw/line_vertical_slope1px_w2px.png new file mode 100644 index 0000000000000000000000000000000000000000..1d48a57e87705b5d9f774abf10cc736201ae0c9f GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1SFYWcSQjy&H|6fVg?3oVGw3ym^DWND9B#o z>FdgVkA+h}M#(v{u?8q);pyTSVsZNEWJMtc1D@s|{}=y=QcqLAcH-KR!i1)%(3?V& wwT#a&2+Y#obNbFB`PTnWi_g4{yLyW`PWnDW#_#1n+a literal 0 HcmV?d00001 diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index 46bb43a11..6b4e74480 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -92,6 +92,11 @@ def test_line_horizontal(): img, draw = create_base_image_draw((200, 110)) draw.line((5, 55, 195, 55), BLACK, 101) assert_image_equal(img, expected, 'line straigth horizontal 101px wide failed') + expected = Image.open(os.path.join(IMAGES_PATH, 'line_horizontal_slope1px_w2px.png')) + expected.load() + img, draw = create_base_image_draw((20, 20)) + draw.line((5, 5, 14, 6), BLACK, 2) + assert_image_equal(img, expected, 'line horizontal 1px slope 2px wide failed') def test_line_vertical(): @@ -118,6 +123,11 @@ def test_line_vertical(): img, draw = create_base_image_draw((110, 200)) draw.line((55, 5, 55, 195), BLACK, 101) assert_image_equal(img, expected, 'line straigth vertical 101px wide failed') + expected = Image.open(os.path.join(IMAGES_PATH, 'line_vertical_slope1px_w2px.png')) + expected.load() + img, draw = create_base_image_draw((20, 20)) + draw.line((5, 5, 6, 14), BLACK, 2) + assert_image_equal(img, expected, 'line vertical 1px slope 2px wide failed') def test_line_oblique_45(): From 113b8c2a7633edb39894b3f3818e2e5b0e871f96 Mon Sep 17 00:00:00 2001 From: Terseus Date: Wed, 9 Apr 2014 20:06:58 +0200 Subject: [PATCH 18/22] Removed non-ASCII character from messages --- Tests/test_imagedraw.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index 6b4e74480..76e602f54 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -135,15 +135,15 @@ def test_line_oblique_45(): expected.load() img, draw = create_base_image_draw((20, 20)) draw.line((5, 5, 14, 14), BLACK, 3) - assert_image_equal(img, expected, 'line oblique 45º normal 3px wide A failed') + assert_image_equal(img, expected, 'line oblique 45 normal 3px wide A failed') img, draw = create_base_image_draw((20, 20)) draw.line((14, 14, 5, 5), BLACK, 3) - assert_image_equal(img, expected, 'line oblique 45º inverted 3px wide A failed') + assert_image_equal(img, expected, 'line oblique 45 inverted 3px wide A failed') expected = Image.open(os.path.join(IMAGES_PATH, 'line_oblique_45_w3px_b.png')) expected.load() img, draw = create_base_image_draw((20, 20)) draw.line((14, 5, 5, 14), BLACK, 3) - assert_image_equal(img, expected, 'line oblique 45º normal 3px wide B failed') + assert_image_equal(img, expected, 'line oblique 45 normal 3px wide B failed') img, draw = create_base_image_draw((20, 20)) draw.line((5, 14, 14, 5), BLACK, 3) - assert_image_equal(img, expected, 'line oblique 45º inverted 3px wide B failed') + assert_image_equal(img, expected, 'line oblique 45 inverted 3px wide B failed') From 668141a898c6b89eec921522650891a8ac899751 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 30 Jun 2014 15:03:57 -0700 Subject: [PATCH 19/22] updated imagedraw tests --- Tests/images/imagedraw_ellipse.png | Bin 491 -> 466 bytes Tests/images/imagedraw_line.png | Bin 286 -> 247 bytes Tests/images/imagedraw_pieslice.png | Bin 405 -> 394 bytes Tests/images/imagedraw_polygon.png | Bin 292 -> 293 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/images/imagedraw_ellipse.png b/Tests/images/imagedraw_ellipse.png index fb03fd148597a95bd4c446243b064e91561973ff..b52b128023c1c7126d5bdf76e82a8b682a0a176a 100644 GIT binary patch delta 440 zcmaFOe2IC2O8rbv7srr_Id5-Y>^o$@;}SSs|NZ=Oc`j9jjcX1X`)&PhqnyO1&a2eP zfB=7PUWz@CSpB`}U(juB38ScZ@y&gK+pgX*{qXkif1wN7-yhsL`up%NrDcKcDbF@+ z>sX&G6{~Dq+tr;uqhp2ttABa<@_eQ?_d6AqsZXmHGcK8Cx6)wi3@aV)AnV$=U*|rl zq)K{AT}$)L+OD_j*`?OhDkn?#@Um(9*UBARd)`|l>^O@|rdxQ+Rcl7~qf;}iR&QUM zVro(UZcbcf#NE|bS5!$mrmG5sIps!twqbWq4Gk^7X2X4L-4?lJiA;$=2^6A!O1_u+ z?IY8#1xsH`x&3|hrd2cAI9sL$$XzqKxM^$NR&D0FQx$$4PHK84bY%fY_Pq3@Le))~ zH*Uwwy6BpyD_C23l5g8fu^;zNR?OP}o?rHM$E&x8P87^IJ7ao7D@zdAjGHK z1a}4msC#oQ_CVtAciexMZVNL|IyU8EMeLc&*W1=C*}m)0uU$XP8TWqTI2XIeevPo< zSt}*u_N}gS`ZCM<&yhLaIlbq1~ zn-`?2cEm;KT-d>4s&Odl`Miq8?`?t?@9r>37jNCVJ}vW<_qGkb<_Er)9qV4ZsB>Os zOU~Xvi)DQ0_8fU0)SfD{=Sy}0@8lrwxM^2Uo%2eJ*er2iw$++$Z!g_(z%L9D{6ARszl^;hS($PRBwbt7#J4x z7$)^Bm;Y!U=WoA2?6FnEHI|K=b{?6V>MM}VI9+0zsp}fkm_;Do%xBXxB887ct^BMS z1ym&V`>BxkyjPP_-!6Ui^;CbU$*pZ)^6lSvt=W6%`a==D5Ye5dSH)@xB~R5Cot|79 zlhhtGanl;LrH|^?*e!kJx2AY5ABYN@?G^A|UX}q3ta!}3Y_APBhp4XwNXFCE&t;uc GLK6T!bX%kV delta 258 zcmey)IFD(9O8rw$7srr_Id5+o@*Oe|a6Q=i`~FRlMh&l)k7}6_=R3IWe0bu|rNqF{ z@c-kBnrpY72fV-HGEcevTGr&(M~fDgwdIL*UyPV0VV@lNXqu#&N>b#b_Yu=}7#(hj zS#xr_g~(|k@w6Ee`b<9yxhF>^%}6{oGvczIq2Otuvjz`S*8CHyj;`L{b@HfGU}iUc+SF*n4YaBvzCN>`9Ja9i$4>>bw#(^ z^Kwt`s!qPDC%QaYcJ~y0(eS)$+s^SUWk3h7su(~0(X!sjaqS>T%G1@)Wt~$(69DQ9 Bb`<~s diff --git a/Tests/images/imagedraw_pieslice.png b/Tests/images/imagedraw_pieslice.png index 1b2acff92ab9aa263ce85ceb1a37493d4cbef6cb..2f8c091915ff0b92b268661484a53660e1abf136 100644 GIT binary patch delta 367 zcmV-#0g(Qc1BwHXB!5v!L_t(|obB4dj>0euMbVe}|9{RbszR%ws8Q|2_S~~%LBo{| zNUa0_00000000000JyEKKERd!=auzGU4McLy&rP5(=nHwIY+FcL%7+8|CxNf=X%%P zv47fDNBLrH&dDap8f!DTSMFGPkJyZrOdo4AXT*xc(v)6xVt?t~%S)+P((C)nMYUKv zmtF;9`7L9?SaMs&nz44qy~@V&SjMukJXDTl{>@c6mN{Y#_z$tnHnDgt+uy|Ev1}1* z0I>!TYe3jot;M^g88(&z_KF-!(Ru}srBJ=%$I_EtwxLtR(zE$83zj98BJ5+LSX$mI zS1b+nYE8D!aA>8ArG@jAF_!N1@(7wVmhR1$aj?9x^re^6o~DkakG=L+?1N>GrHlD; z8La}bbnIpRcj0syr}tgqb#tQ9hjKLav3LLg00000000000002^<`-z9H)g~J$2kB1 N002ovPDHLkV1nlcxC;OP delta 378 zcmeBTp2|Eyr9Q^f#WAE}&f8lT`D@AH#EY)kO>DGhb?^=Pvrfa=}fN z0S*r2rha2Mccp&*8TnU#1m~>SdOFnWf2-F_<2Mo;t72DNZ2m7p$<`^Az4^OU?3QJZ-bS|Ha(ni>IO+VFyE9a0)~ifw`*KRyd+qf5|E6k9`dMdka4gKN7L)a<_ZpUhB`NEh6qj?0WHZi=XrH zONsjX#cwYgNh{x{*6sdKD7F0YxefMnPJCG`!&|E>2M;9>W8EJnR~h?^ S@T=4GL0nH)KbLh*2~7a8ezuVS diff --git a/Tests/images/imagedraw_polygon.png b/Tests/images/imagedraw_polygon.png index 5f160be76ceef3d85c7092a63d87e48115ec3303..7199a25dd7789faf617b9a518e1f306676c69ac5 100644 GIT binary patch delta 266 zcmZ3&w3KOrO8py87srr_Id5-T=N&N+a5=c_eSNys0@_7DH@%`hro;7xT+4xnKG&+;`iN@*3$JgB(7cds zdaZxD#hkm@&o{L-SHJC_T3j95@%6YWpZm9}lt|C0s!MWJKUUiay*?4NQ|k40Z=05;BxTNT4527UjzX}^Oe0~%;x-oyN!%|$54V(Na7l&7no K%Q|MKgeCx~&U>o> delta 265 zcmZ3=w1jDbO8sk37srr_Id5+q%sOl!;&L(Y|Nr?{TX%8gPRyCPrRw>b#|e6$IaC-K z82B#z-hKap{L3oci`fS?mR_H7Pk8UMms3^bz30EnTwAbyYlP`T{G!}cA2n#ybX zz0@$w>)WjUt5I>MLtdBGMmn#ID^Fe;w0>#C{g_7qORl%2@`_gF)^|^3+8dVqx1#g# z&AnxM*%mvl|BJBP9=`ia$a`V_ZC_U3|L< Date: Tue, 1 Jul 2014 09:07:18 -0700 Subject: [PATCH 20/22] Skip known failing test --- Tests/test_imagedraw.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index b9bedf33e..4610e2b0b 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -317,6 +317,9 @@ class TestImageDraw(PillowTestCase): img, draw = self.create_base_image_draw((200, 110)) draw.line((5, 55, 195, 55), BLACK, 101) self.assert_image_equal(img, expected, 'line straigth horizontal 101px wide failed') + + def test_line_h_s1_w2(self): + self.skipTest('failing') expected = Image.open(os.path.join(IMAGES_PATH, 'line_horizontal_slope1px_w2px.png')) expected.load() img, draw = self.create_base_image_draw((20, 20)) From a10b91786a3c1e0e9355b79ccb2220a7b2dd8874 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 1 Jul 2014 10:05:38 -0700 Subject: [PATCH 21/22] Fix compilation errors with C90 standard --- libImaging/Draw.c | 48 ++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/libImaging/Draw.c b/libImaging/Draw.c index 2f53fde79..307bb4425 100644 --- a/libImaging/Draw.c +++ b/libImaging/Draw.c @@ -421,19 +421,24 @@ static inline int polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler hline) { + + Edge** edge_table; + float* xx; + int edge_count = 0; + int ymin = im->ysize - 1; + int ymax = 0; + int i; + if (n <= 0) { return 0; } /* Initialize the edge table and find polygon boundaries */ - Edge** edge_table = malloc(sizeof(Edge*) * n); + edge_table = malloc(sizeof(Edge*) * n); if (!edge_table) { return -1; } - int edge_count = 0; - int ymin = im->ysize - 1; - int ymax = 0; - int i; + for (i = 0; i < n; i++) { /* This causes that the pixels of horizontal edges are drawn twice :( * but without it there are inconsistencies in ellipses */ @@ -457,7 +462,7 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, } /* Process the edge table with a scan line searching for intersections */ - float* xx = malloc(sizeof(float) * edge_count * 2); + xx = malloc(sizeof(float) * edge_count * 2); if (!xx) { free(edge_table); return -1; @@ -591,6 +596,11 @@ ImagingDrawWideLine(Imaging im, int x0, int y0, int x1, int y1, { DRAW* draw; INT32 ink; + int dx, dy; + double big_hypotenuse, small_hypotenuse, ratio_max, ratio_min; + int dxmin, dxmax, dymin, dymax; + Edge e[4]; + int vertices[4][2]; DRAWINIT(); @@ -599,35 +609,35 @@ ImagingDrawWideLine(Imaging im, int x0, int y0, int x1, int y1, return 0; } - int dx = x1-x0; - int dy = y1-y0; + dx = x1-x0; + dy = y1-y0; if (dx == 0 && dy == 0) { draw->point(im, x0, y0, ink); return 0; } - double big_hypotenuse = sqrt((double) (dx*dx + dy*dy)); - double small_hypotenuse = (width - 1) / 2.0; - double ratio_max = ROUND_UP(small_hypotenuse) / big_hypotenuse; - double ratio_min = ROUND_DOWN(small_hypotenuse) / big_hypotenuse; + big_hypotenuse = sqrt((double) (dx*dx + dy*dy)); + small_hypotenuse = (width - 1) / 2.0; + ratio_max = ROUND_UP(small_hypotenuse) / big_hypotenuse; + ratio_min = ROUND_DOWN(small_hypotenuse) / big_hypotenuse; - int dxmin = ROUND_DOWN(ratio_min * dy); - int dxmax = ROUND_DOWN(ratio_max * dy); - int dymin = ROUND_DOWN(ratio_min * dx); - int dymax = ROUND_DOWN(ratio_max * dx); - int vertices[4][2] = { + dxmin = ROUND_DOWN(ratio_min * dy); + dxmax = ROUND_DOWN(ratio_max * dy); + dymin = ROUND_DOWN(ratio_min * dx); + dymax = ROUND_DOWN(ratio_max * dx); + + vertices = (int[][]) { {x0 - dxmin, y0 + dymax}, {x1 - dxmin, y1 + dymax}, {x1 + dxmax, y1 - dymin}, {x0 + dxmax, y0 - dymin} }; - Edge e[4]; add_edge(e+0, vertices[0][0], vertices[0][1], vertices[1][0], vertices[1][1]); add_edge(e+1, vertices[1][0], vertices[1][1], vertices[2][0], vertices[2][1]); add_edge(e+2, vertices[2][0], vertices[2][1], vertices[3][0], vertices[3][1]); add_edge(e+3, vertices[3][0], vertices[3][1], vertices[0][0], vertices[0][1]); - + draw->polygon(im, 4, e, ink, 0); return 0; From 98a49917629702c882575fa34985bb00f545b032 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 1 Jul 2014 10:20:15 -0700 Subject: [PATCH 22/22] Using local block rather than array literal --- libImaging/Draw.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/libImaging/Draw.c b/libImaging/Draw.c index 307bb4425..2ff03e049 100644 --- a/libImaging/Draw.c +++ b/libImaging/Draw.c @@ -625,21 +625,21 @@ ImagingDrawWideLine(Imaging im, int x0, int y0, int x1, int y1, dxmax = ROUND_DOWN(ratio_max * dy); dymin = ROUND_DOWN(ratio_min * dx); dymax = ROUND_DOWN(ratio_max * dx); - - vertices = (int[][]) { - {x0 - dxmin, y0 + dymax}, - {x1 - dxmin, y1 + dymax}, - {x1 + dxmax, y1 - dymin}, - {x0 + dxmax, y0 - dymin} - }; + { + int vertices[4][2] = { + {x0 - dxmin, y0 + dymax}, + {x1 - dxmin, y1 + dymax}, + {x1 + dxmax, y1 - dymin}, + {x0 + dxmax, y0 - dymin} + }; - add_edge(e+0, vertices[0][0], vertices[0][1], vertices[1][0], vertices[1][1]); - add_edge(e+1, vertices[1][0], vertices[1][1], vertices[2][0], vertices[2][1]); - add_edge(e+2, vertices[2][0], vertices[2][1], vertices[3][0], vertices[3][1]); - add_edge(e+3, vertices[3][0], vertices[3][1], vertices[0][0], vertices[0][1]); - - draw->polygon(im, 4, e, ink, 0); + add_edge(e+0, vertices[0][0], vertices[0][1], vertices[1][0], vertices[1][1]); + add_edge(e+1, vertices[1][0], vertices[1][1], vertices[2][0], vertices[2][1]); + add_edge(e+2, vertices[2][0], vertices[2][1], vertices[3][0], vertices[3][1]); + add_edge(e+3, vertices[3][0], vertices[3][1], vertices[0][0], vertices[0][1]); + draw->polygon(im, 4, e, ink, 0); + } return 0; }