[Image-SIG] fix for wide line directional dependence

Randolph Bentson bentson at holmsjoen.com
Sun Oct 4 00:56:00 CEST 2009


On Wed, Sep 30, 2009 at 07:56:32AM -0700, Randolph Bentson wrote:
> I've found that wide lines drawn with PIL 1.1.6 have a directional
> dependence, e.g., lines from (0,0) to (-100,0) are thinner than those
> from (0,0) to (0,-100).

A few days ago I posted a hack which reduced the magnitude of the problem.
The following patch does a better job at little additional cost.

I've introduced variables dX and dY to improve the readability of the
code which computes the values of the pixel-based dx and dy values. The
reference to "diagonal lines" doesn't implement proper antialiasing,
but it improves things with modest code change.)

Feedback is welcome because I do hope this'll get in the 1.1.7 release.


--- OLD_Draw.c	2009-10-03 14:44:31.000000000 -0700
+++ Draw.c	2009-10-03 15:42:41.000000000 -0700
@@ -665,6 +665,7 @@
 
     Edge e[4];
 
+    int dX, dY;
     int dx, dy;
     double d;
 
@@ -675,18 +676,34 @@
         return 0;
     }
 
-    dx = x1-x0;
-    dy = y1-y0;
+    dX = x1-x0;
+    dY = y1-y0;
 
-    if (dx == 0 && dy == 0) {
+    if (dX == 0 && dY == 0) {
         draw->point(im, x0, y0, ink);
         return 0;
     }
 
-    d = width / sqrt(dx*dx + dy*dy) / 2.0;
+    d = width / sqrt(dX*dX + dY*dY) / 2.0;
 
-    dx = (int) (d * (y1-y0) + 0.5);
-    dy = (int) (d * (x1-x0) + 0.5);
+    /* Negative values are rounded down and positive
+       values are rounded up, else the deltas disappear!
+     */
+    if (dY < 0)  dx = (int) (d * dY - 0.5);
+    else         dx = (int) (d * dY + 0.5);
+    if (dX < 0)  dy = (int) (d * dX - 0.5);
+    else         dy = (int) (d * dX + 0.5);
+
+    /* This is necessary because diagonal lines are too wide.
+     */
+    if ( 4*(dx*dx+dy*dy) > (width*width) ){
+        if (abs(dx) > abs(dy))
+            if (dx < 0) dx ++;
+            else        dx --;
+        else
+            if (dy < 0) dy ++;
+            else        dy --;
+    }
 
     add_edge(e+0, x0 - dx,  y0 + dy, x1 - dx,  y1 + dy);
     add_edge(e+1, x1 - dx,  y1 + dy, x1 + dx,  y1 - dy);

-- 
Randolph Bentson
bentson at holmsjoen.com


More information about the Image-SIG mailing list