we (web engine): Experimental web browser project to understand the limits of Claude
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix LZW code size increment to use early change (>= instead of >)

GIF LZW uses "early change" — the code size must bump when next_code
reaches (1 << code_size), not after it exceeds it. Without this fix,
the decoder would read codes with the wrong bit width for GIFs with
enough unique codes to trigger a code size increase.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

authored by

Pierre Le Fevre
Claude Opus 4.6
and committed by tangled.org 4bd95245 4adef4d8

+9 -9
+9 -9
crates/image/src/gif.rs
··· 147 147 if self.next_code < 4096 { 148 148 self.table.push((prefix, suffix)); 149 149 self.next_code += 1; 150 - // Increase code size when we've filled the current capacity 151 - if self.next_code > (1 << self.code_size) && self.code_size < 12 { 150 + // Increase code size when all codes at the current size are used (early change) 151 + if self.next_code >= (1 << self.code_size) && self.code_size < 12 { 152 152 self.code_size += 1; 153 153 } 154 154 } ··· 848 848 fn lzw_simple_sequence() { 849 849 // LZW with min code size 2 (codes 0-3 are literal, 4=clear, 5=eoi) 850 850 // Encode a simple sequence: clear, 0, 1, 0, 1, eoi 851 - // Using 3-bit codes (min_code_size=2, initial code_size=3) 851 + // initial code_size=3, bumps to 4 after next_code reaches 8 852 852 let mut bits: u64 = 0; 853 853 let mut bit_pos = 0u32; 854 854 ··· 856 856 (4, 3), // clear code 857 857 (0, 3), // literal 0 858 858 (1, 3), // literal 1 859 - (0, 3), // literal 0 860 - (1, 3), // literal 1 861 - (5, 3), // eoi 859 + (0, 3), // literal 0 → add_entry makes next_code=8, code_size→4 860 + (1, 4), // literal 1 (now 4 bits) 861 + (5, 4), // eoi (4 bits) 862 862 ]; 863 863 864 864 for &(code, nbits) in codes { ··· 1256 1256 // LZW min code size = 2 (4 literal codes: 0,1,2,3; clear=4, eoi=5) 1257 1257 gif.push(2); 1258 1258 1259 - // Encode: clear(4), 0, 1, 2, 3, eoi(5) — all 3-bit codes 1260 - // 9 codes * 3 bits = 18 bits = 3 bytes (with padding) 1259 + // Encode: clear(4), 0, 1, 2, 3, eoi(5) 1260 + // code_size starts at 3, bumps to 4 after code 2 (next_code reaches 8) 1261 1261 let mut bits: u64 = 0; 1262 1262 let mut bp = 0u32; 1263 - for &(code, nbits) in &[(4u16, 3u8), (0, 3), (1, 3), (2, 3), (3, 3), (5, 3)] { 1263 + for &(code, nbits) in &[(4u16, 3u8), (0, 3), (1, 3), (2, 3), (3, 4), (5, 4)] { 1264 1264 bits |= (code as u64) << bp; 1265 1265 bp += nbits as u32; 1266 1266 }