[racket-dev] Bug report and complaint: Bitmap drawing and masks
Thanks for the bug reports! I've pushed some fixes to the repo -- more
details and answers below.
At Tue, 14 Dec 2010 20:46:27 -0800, John Boyle wrote:
> Problem: The dc% method 'draw-bitmap-section disregards the boundaries of
> the drawing section when the 'color argument is the color black.
You're right that the color should not have mattered. For a non-black
color, `draw-bitmap-section' was taking an unnecessary slow path; the
slow path turned out to be more correct than the faster path. I've
fixed both the unnecessary indirection and the fast path.
> Next, I complain about some other weird behavior of bitmaps (this behavior
> has, I think, existed for a long time). In the following example (code at
> the bottom of this email), I load a black-and-white bitmap (which seems to
> load as color), then create two bitmaps inside bitmap-dc%s (one monochrome
> and the other color), draw the original black-and-white bitmap to each of
> these bitmap-dc%s, and extract the bitmaps from the bitmap-dc%s. Now I have
> three black-and-white bitmaps that all look identical: the originally loaded
> one, the monochrome copy, and the color copy.
>
> Now I try to use them as masks to draw the "valkyrie" bitmaps. What
> happens? The first one works, the second and third don't. Why is this? I
> investigated and found that, while the pixels of the copies are identical to
> those of the original (at least, the color copy is identical to the
> original), the "alpha" channel is different: the alpha bytes are all 0 on
> the original, but they're all 255 on both of the copies.
>
> Questions/complaints:
> 1. Why does the alpha channel of a bitmap matter when it's being used as a
> mask?
It turns out that if a bitmap has an alpha channel, then when the
bitmap is used as a mask, only its alpha channel is used for masking.
That wasn't documented (and it took me a while to remember); I've fixed
the docs.
While this rule may seem somewhat arbitrary, it works well with the
underlying Cairo API. The idea is that if you want to construct a
grayscale mask separate from content to draw, it's really better to
think in terms of constructing a suitable alpha channel.
> 2. Why doesn't drawing a bitmap to another one of the same size produce an
> exact copy of the first?
In the case of `u' versus `cu', you're starting with a bitmap that has
no alpha channel and drawing into a bitmap that does have an alpha
channel. If you add a #f to the call to `make-bitmap' to disable the
alpha channel, then you do get the same bitmap for `cu'.
> (Or, if, say, the second one is monochrome while
> the first is color, why doesn't it produce the monochrome equivalent of the
> first? And vice versa.)
The result of drawing with `mu' as a mask was broken. The problem was
in `draw-bitmap' with a monochrome target bitmap. A monochome bitmap
actually has an alpha channel internally, where drawing with black sets
the alpha channel to 255 and drawing with white sets it to 255. The
`draw-bitmap' operation wasn't preserving that correspondence, and it's
now fixed.
There was also a bug related to using a color bitmaps as a mask,
drawing on it, and then using the bitmap as a mask again. That's also
now fixed.