add docs to address how image equality, rounding, and alpha values
can conspire to confuse closes PR 13541
This commit is contained in:
parent
17d6e162bc
commit
d403f3c6db
|
@ -410,3 +410,55 @@ within the bounding box, we see only three black pixels and one white one.
|
||||||
|
|
||||||
The black pixels are (most of) the upper and left edge of the outline shape,
|
The black pixels are (most of) the upper and left edge of the outline shape,
|
||||||
and the one white pixel is the pixel in the middle of the shape.
|
and the one white pixel is the pixel in the middle of the shape.
|
||||||
|
|
||||||
|
@section[#:tag "nitty-gritty-alpha"]{The Nitty Gritty of Alpha Blending}
|
||||||
|
|
||||||
|
Alpha blending can cause imprecision in color comparisons resulting in
|
||||||
|
shapes that appear @racket[equal?] even though they were created with
|
||||||
|
different colors. This section explains how that happens.
|
||||||
|
|
||||||
|
To start, consider the color @racket[(make-color 1 1 1 50)].
|
||||||
|
This color is nearly the darkest shade of black, but with lots of transparency,
|
||||||
|
to it renders a light gray color on a white background, e.g.:
|
||||||
|
@image-interaction[(rectangle 100 100 "solid" (make-color 1 1 1 50))]
|
||||||
|
If the background had been green, the same rectangle would look like a darker shade of green:
|
||||||
|
@image-interaction[(overlay
|
||||||
|
(rectangle 100 100 "solid" (make-color 1 1 1 50))
|
||||||
|
(rectangle 200 200 "solid" "green"))]
|
||||||
|
|
||||||
|
Surprisingly, this shape is equal to one that (apparently) has a different
|
||||||
|
color in it:
|
||||||
|
@image-interaction[(equal?
|
||||||
|
(rectangle 100 100 'solid (make-color 1 1 1 50))
|
||||||
|
(rectangle 100 100 'solid (make-color 2 2 2 50)))]
|
||||||
|
To understand why, we must look more carefully at how alpha blending
|
||||||
|
and image equality work. Image equality is straightforward: two images
|
||||||
|
are equality if they are both drawn the same. That is, image equality
|
||||||
|
is defined by simply drawing the two shapes on a white background and
|
||||||
|
then comparing all of the pixels for the two drawings
|
||||||
|
(it is implemented more efficiently in some cases, however).
|
||||||
|
|
||||||
|
So, for those shapes to be equal, they must be drawn with the same colors.
|
||||||
|
To see what colors were actually drawn, we can use @racket[image->color-list].
|
||||||
|
Since these images use the same color in every pixel, we can examine just the first one:
|
||||||
|
@image-interaction[(first
|
||||||
|
(image->color-list
|
||||||
|
(rectangle 100 100 'solid (make-color 1 1 1 50))))
|
||||||
|
(first
|
||||||
|
(image->color-list
|
||||||
|
(rectangle 100 100 'solid (make-color 2 2 2 50))))]
|
||||||
|
As expected from the @racket[equal?] test, the two colors are the same, but
|
||||||
|
why should they be the same? This is where a subtle aspect of alpha blending
|
||||||
|
and drawing comes up. In general, alpha blending works by taking the color
|
||||||
|
of any shapes below the one being drawn and then combining that color with
|
||||||
|
the new color. The precise amount of the combination is controlled by the alpha value.
|
||||||
|
So, if a shape has an alpha value of @racket[α], then the drawing library
|
||||||
|
multiplies the new shapes color by @racket[(/ α 255)] and the existing shape's
|
||||||
|
color by @racket[(- 1 (/ α 255))] and then adds the results to get the final color.
|
||||||
|
(It does this for each of the red, green, and blue components separately.)
|
||||||
|
|
||||||
|
Going back to the two example rectangles,
|
||||||
|
the drawing library multiplies @code{50/255} by @racket[1] for the first
|
||||||
|
shape and multiplies @code{50/255} by @racket[2] for the second shape (since they
|
||||||
|
are both drawn on a white background). Then rounds them to integers, which
|
||||||
|
results in @racket[0] for both colors, making the images the same.
|
||||||
|
|
|
@ -1293,6 +1293,9 @@ See also the @racketmodname[2htdp/planetcute] library.
|
||||||
Returns a list of colors that correspond to the colors in the
|
Returns a list of colors that correspond to the colors in the
|
||||||
image, reading from left to right, top to bottom.
|
image, reading from left to right, top to bottom.
|
||||||
|
|
||||||
|
The list of colors is obtained by drawing the image on a white
|
||||||
|
background and then reading off the colors of the pixels that were drawn.
|
||||||
|
|
||||||
@image-examples[(image->color-list (rectangle 2 2 "solid" "black"))
|
@image-examples[(image->color-list (rectangle 2 2 "solid" "black"))
|
||||||
(image->color-list
|
(image->color-list
|
||||||
(above (beside (rectangle 1 1 "solid" (make-color 1 1 1))
|
(above (beside (rectangle 1 1 "solid" (make-color 1 1 1))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user