[racket] off-by-1 pixel error in 2htdp/image

From: Stephen Bloch (bloch at adelphi.edu)
Date: Mon Dec 17 07:21:56 EST 2012

On Dec 17, 2012, at 12:09 AM, D Herring wrote:

> I was writing a bit of code to generate a diagram, and bumped into an off-by-one error.  Not sure whether its in my understanding of or use of the 2htdp/image library.  Testing on DrRacket 5.3.1 on 64-bit linux.
> ...
> The code runs, but there is a one-pixel white gap between each (line 0 15 "black") and the box below it.  Also, the anti-aliasing is rendering the line into the box above it.  The save-image output is attached (and matches a screenshot).

I'm not seeing the one-pixel white gap or the "rendering the line into the box above it" (although that could just be that the pixels on the screen are smaller than the resolution of my eyes at 7 AM).  I'm seeing the right-hand and bottom edges chopped off in the saved file, but not in the Interactions pane.  I'm on a Mac (10.6.8) with DrRacket 5.3.1.

I tried replacing the (line 0 15 "black") with (rectangle 1 15 "solid" "black"); no visible difference.

> Now the questions.  What is the preferred image library in Racket?

Well, 2htdp/image was designed to be beginner-friendly

>  Am I misusing 'above, or is there an off-by-1 error in its implementation? (e.g. in above/internal or overlay/δ in collects/2htdp/private/image-more.rkt)


The problem, in a nutshell, is that outlined geometric shapes have mathematically correct bounding boxes, but the pixels they color are down and to the right of those bounding boxes.  And "save-image", reasonably enough, only saves the pixels inside the bounding box.  We've been running into things like this for years.  No, you're not misusing 'above, and no, there isn't an off-by-1 error in its implementation; if anything, there's an off-by-1 error in its specification :-)

As an illustration, if you replace (line 0 15 "black") with (rectangle 1 15 "outline" "black") you get a 2-pixel-wide line -- the left and right edges of a mathematically 1x15 rectangle.

We HAVE been running into things like this for years, and are likely to continue running into things like this.  One solution floated in the past is that the "bounding box" isn't really the bounds on what pixels an image colors (in which case one wonders what name to use for the ACTUAL bounding box).  Perhaps the right answer is that outlined geometric shapes should color whatever pixel is closest to the bounding box but not outside it.  This would mean that if you put one outlined rectangle above another, you get a double-thick horizontal line where they meet -- which, while annoying, would at least be easier for beginners to understand.  And it would mean that (rectangle 1 15 "outline" "black") draws as 1 pixel wide.


Stephen Bloch
sbloch at adelphi.edu



Posted on the users mailing list.