No behavior change. No measurable performance different either.
(I tried `hyperfine 'Build/lagom/bin/image --no-output foo.webp'`
for a few input images before and after this change, and I didn't
see a difference. I also tried if moving both
Gfx::CanonicalCode::read_symbol() and
Compress::CanonicalCode::read_symbol() inline, and that didn't
help either.)
This used to be misleading in the spec, but that was fixed in
4674031
Update the comments to match.
Also, a check we already had got added to the spec in
4674032
so add a citation for that.
No behavior change.
This doesn't use any transforms yet (in particular not the predictor
transform), and doesn't do anything else that actually compresses the
data.
It also give all 256 values code length 8 unconditionally. This means
the huffman trees are not data-dependent at all and provide no
compression. It also means we can just write out the image data
unmodified.
So the output is fairly large. But it _is_ a valid lossless webp file.
Possible follow-ups, to improve compression later:
1. Use actual byte distributions to create huffman trees, to get
huffman compression.
2. If the distribution has just 1 element, write a simple code length
code (that way, images that have alpha 0xff everywhere need to store
no data for alpha).
3. Add backref support, to get full deflate(ish) compression of pixels.
4. Add predictor transform.
5. Consider writing different sets of prefix codes for every 16x16 tile
(by writing a meta prefix code image).
(It might be nice to make the follow-ups optional, so that this can also
be used as a webp example file generator.)
If a lossless webp has 3 or 4 colors, it uses 2 bits per pixel to
store an offset into a "color index" (which the spec explicitly does
not call palette since it says the 'color cache' is more like that).
This way, it can pack 4 pixels into a single pixel.
If the width of the output image wasn't evenly divisble by 4,
we used to write out-of-bounds in the last few columns of each
row, since we used to always write all 4 pixels.
Found by clusterfuzz. Probably fixes
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=66082
While here, spruce up the comments very slightly.
simple-vp8l-alpha-used-false.webp is a copy of simple-vp8l.webp,
with the byte at offset 0x18 changed from 0x10 to 0x00 -- that
is, the bit in the VP8L header that stores `is_alpha_used` is cleared.
We would already allocated a BGRx8888 instead of a BGRA8888 bitmap,
but keep actual alpha data in the `x` channel.
That lead to at least `image` still writing a PNG with an alpha channel.
So explicitly set the alpha channel to 0xff when is_alpha_used is false,
to make sure all consumers of decoded lossless webp data have behavior
consistent with other webp readers.
In practice, webp encoders usually don't write files that have
`is_alpha_used` set to false and then write actual alpha data to their
output. So this is rarely observable. However, for example for
lossy+ALPH webp files, the lossless webp used to store the ALPH channel
has `is_alpha_used` set to false and all channels but green are 0
(since the lossless green channel stores the alpha channel of a
lossy+ALPH webp). So if we dump such a bitmap to a standalone webp
file (e.g. with the temporary debugging code in fc3249a1ca),
then without this commit here, `image` would convert that webp to
a fully transparent webp, while other webp software would correctly
display the green image with opaque alpha.