Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion format/riff/testdata/4x4.lossless.webp.fqtest
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ $ fq -d webp dv 4x4.lossless.webp
0x00| 56 50 38 4c| VP8L| id: "VP8L" 0xc-0x10 (4)
0x10|0e 00 00 00 |.... | size: 14 0x10-0x14 (4)
0x10| 2f | / | signature: 0x2f (valid) 0x14-0x15 (1)
0x10| 03 c0 00 00 | .... | width_height_flags: 49155 0x15-0x19 (4)
0x10| 03 c0 00 00 | .... | width_height_flags: 0xc003 0x15-0x19 (4)
| | | width: 4
| | | height: 4
| | | alpha_is_used: false
Expand Down
31 changes: 31 additions & 0 deletions format/riff/testdata/vp8k-sizes.fqtest
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# for s in 1x1 1x7 7x1 616x232 10921x10921 16383x16383; do gm convert -size $s 'xc:#ffffff' -define webp:lossless=true vp8l-$s.webp ; done
$ fq -rV '.chunks[0] | .id, "\(.width)x\(.height)", .alpha_is_used, .version_number' vp8l-1x1.webp
VP8L
1x1
false
0
$ fq -rV '.chunks[0] | .id, "\(.width)x\(.height)", .alpha_is_used, .version_number' vp8l-1x7.webp
VP8L
1x7
false
0
$ fq -rV '.chunks[0] | .id, "\(.width)x\(.height)", .alpha_is_used, .version_number' vp8l-7x1.webp
VP8L
7x1
false
0
$ fq -rV '.chunks[0] | .id, "\(.width)x\(.height)", .alpha_is_used, .version_number' vp8l-616x232.webp
VP8L
616x232
false
0
$ fq -rV '.chunks[0] | .id, "\(.width)x\(.height)", .alpha_is_used, .version_number' vp8l-10921x10921.webp
VP8L
10921x10921
false
0
$ fq -rV '.chunks[0] | .id, "\(.width)x\(.height)", .alpha_is_used, .version_number' vp8l-16383x16383.webp
VP8L
16383x16383
false
0
Binary file added format/riff/testdata/vp8l-10921x10921.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added format/riff/testdata/vp8l-16383x16383.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added format/riff/testdata/vp8l-1x1.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added format/riff/testdata/vp8l-1x7.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added format/riff/testdata/vp8l-616x232.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added format/riff/testdata/vp8l-7x1.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions format/riff/testdata/vp8l-alpha.fqtest
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# gm convert 'xc:transparent' -define webp:lossless=true vp8l-alpha.webp
$ fq -rV '.chunks[0] | .id, "\(.width)x\(.height)", .alpha_is_used, .version_number' vp8l-alpha.webp
VP8L
1x1
true
0
Binary file added format/riff/testdata/vp8l-alpha.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 24 additions & 9 deletions format/riff/webp.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,33 @@ func webpDecode(d *decode.D) any {
return false, nil
case "VP8L":
d.FieldU8("signature", d.UintAssert(0x2f), scalar.UintHex)
n := d.FieldU32("width_height_flags")
// TODO: replace with "bit endian" decoding

// From https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification
// > The bytes are read in the natural order of the stream containing them,
// > and bits of each byte are read in least-significant-bit-first order.
// > When multiple bits are read at the same time, the integer is constructed
// > from the original data in the original order. The most significant bits
// > of the returned integer are also the most significant bits of the original
// > data.
//
// Not sure how much wiser i got reading that but by trail and error i think it's
// encoded like this if read as a 32 LE number:
// 01234567|01234567|01234567|01234567
// vvvahhhh|hhhhhhhh|hhwwwwww|wwwwwwww
//
// TODO: replace with "bit endian" decoding?

n := d.FieldU32("width_height_flags", scalar.UintHex)
b0 := (n >> 24) & 0xff
b1 := (n >> 16) & 0xff
b2 := (n >> 8) & 0xff
b3 := (n >> 0) & 0xf
width := b3 | (b2&0b0011_111)<<8
width += 1
height := (b2&0b1100_0000)>>6 | b1<<8 | (b0&0b0000_1111)<<16
height += 1
alphaIsUsed := b3&0b0001_0000 != 0
versionNumber := (b3 & 0b1110_0000) >> 5
b3 := (n >> 0) & 0xff

width := ((b2&0b0011_1111)<<8 | b3) + 1
height := ((b0&0b0000_1111)<<10 | (b1 << 2) | ((b2 & 0b1100_0000) >> 6)) + 1
alphaIsUsed := b0&0b0001_0000 != 0
versionNumber := (b0 & 0b1110_0000) >> 5

d.FieldValueUint("width", width)
d.FieldValueUint("height", height)
d.FieldValueBool("alpha_is_used", alphaIsUsed)
Expand Down
Loading