Skip to main content

webp_rust/decoder/
lossless.rs

1//! Lossless `VP8L` decode helpers.
2
3use std::collections::HashMap;
4
5use crate::decoder::header::parse_still_webp;
6use crate::decoder::lossy::DecodedImage;
7use crate::decoder::vp8::get_lossless_info;
8use crate::decoder::vp8i::WebpFormat;
9use crate::decoder::DecoderError;
10
11const ARGB_BLACK: u32 = 0xff00_0000;
12const MAX_ALLOWED_CODE_LENGTH: usize = 15;
13const MAX_CACHE_BITS: usize = 11;
14const NUM_LITERAL_CODES: usize = 256;
15const NUM_LENGTH_CODES: usize = 24;
16const NUM_DISTANCE_CODES: usize = 40;
17const NUM_CODE_LENGTH_CODES: usize = 19;
18const MIN_HUFFMAN_BITS: usize = 2;
19const NUM_HUFFMAN_BITS: usize = 3;
20const MIN_TRANSFORM_BITS: usize = 2;
21const NUM_TRANSFORM_BITS: usize = 3;
22const DEFAULT_CODE_LENGTH: u8 = 8;
23const CODE_LENGTH_REPEAT_CODE: usize = 16;
24const CODE_LENGTH_EXTRA_BITS: [usize; 3] = [2, 3, 7];
25const CODE_LENGTH_REPEAT_OFFSETS: [usize; 3] = [3, 3, 11];
26const CODE_LENGTH_CODE_ORDER: [usize; NUM_CODE_LENGTH_CODES] = [
27    17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
28];
29const CODE_TO_PLANE: [u8; 120] = [
30    0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a, 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39,
31    0x15, 0x1b, 0x36, 0x3a, 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b, 0x46, 0x4a,
32    0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03, 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d,
33    0x44, 0x4c, 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e, 0x66, 0x6a, 0x22, 0x2e,
34    0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b, 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
35    0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b, 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e,
36    0x00, 0x74, 0x7c, 0x41, 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f, 0x40, 0x72,
37    0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70,
38];
39const COLOR_CACHE_HASH_MUL: u32 = 0x1e35_a7bd;
40
41#[derive(Debug, Clone)]
42struct LosslessBitReader<'a> {
43    data: &'a [u8],
44    bit_pos: usize,
45}
46
47impl<'a> LosslessBitReader<'a> {
48    fn new(data: &'a [u8]) -> Self {
49        Self { data, bit_pos: 0 }
50    }
51
52    fn read_bit(&mut self) -> Result<u32, DecoderError> {
53        self.read_bits(1)
54    }
55
56    fn read_bits(&mut self, num_bits: usize) -> Result<u32, DecoderError> {
57        if num_bits > 24 {
58            return Err(DecoderError::InvalidParam("VP8L bit read is too wide"));
59        }
60        let end = self
61            .bit_pos
62            .checked_add(num_bits)
63            .ok_or(DecoderError::Bitstream("VP8L bit position overflow"))?;
64        if end > self.data.len() * 8 {
65            return Err(DecoderError::NotEnoughData("VP8L bitstream"));
66        }
67
68        let mut value = 0u32;
69        for bit_index in 0..num_bits {
70            let stream_bit = self.bit_pos + bit_index;
71            let byte = self.data[stream_bit >> 3];
72            let bit = (byte >> (stream_bit & 7)) & 1;
73            value |= (bit as u32) << bit_index;
74        }
75        self.bit_pos = end;
76        Ok(value)
77    }
78}
79
80#[derive(Debug, Clone)]
81struct HuffmanTree {
82    single_symbol: Option<u16>,
83    by_len: Vec<HashMap<u16, u16>>,
84    max_len: usize,
85}
86
87impl HuffmanTree {
88    fn from_code_lengths(code_lengths: &[u8]) -> Result<Self, DecoderError> {
89        let mut counts = [0i32; MAX_ALLOWED_CODE_LENGTH + 1];
90        let mut single_symbol = None;
91        let mut num_symbols = 0usize;
92
93        for (symbol, &len) in code_lengths.iter().enumerate() {
94            let bits = len as usize;
95            if bits > MAX_ALLOWED_CODE_LENGTH {
96                return Err(DecoderError::Bitstream("invalid VP8L Huffman code length"));
97            }
98            if bits > 0 {
99                counts[bits] += 1;
100                single_symbol = Some(symbol as u16);
101                num_symbols += 1;
102            }
103        }
104
105        if num_symbols == 0 {
106            return Err(DecoderError::Bitstream("empty VP8L Huffman tree"));
107        }
108        if num_symbols == 1 {
109            return Ok(Self {
110                single_symbol,
111                by_len: Vec::new(),
112                max_len: 0,
113            });
114        }
115
116        let mut left = 1i32;
117        for bits in 1..=MAX_ALLOWED_CODE_LENGTH {
118            left = (left << 1) - counts[bits];
119            if left < 0 {
120                return Err(DecoderError::Bitstream("oversubscribed VP8L Huffman tree"));
121            }
122        }
123        if left != 0 {
124            return Err(DecoderError::Bitstream("incomplete VP8L Huffman tree"));
125        }
126
127        let mut next_code = [0u32; MAX_ALLOWED_CODE_LENGTH + 1];
128        let mut code = 0u32;
129        for bits in 1..=MAX_ALLOWED_CODE_LENGTH {
130            code = (code + counts[bits - 1] as u32) << 1;
131            next_code[bits] = code;
132        }
133
134        let mut by_len = (0..=MAX_ALLOWED_CODE_LENGTH)
135            .map(|_| HashMap::new())
136            .collect::<Vec<_>>();
137        let mut max_len = 0usize;
138
139        for (symbol, &len) in code_lengths.iter().enumerate() {
140            let bits = len as usize;
141            if bits == 0 {
142                continue;
143            }
144            let canonical = next_code[bits];
145            next_code[bits] += 1;
146            by_len[bits].insert(reverse_bits(canonical, bits), symbol as u16);
147            max_len = max_len.max(bits);
148        }
149
150        Ok(Self {
151            single_symbol: None,
152            by_len,
153            max_len,
154        })
155    }
156
157    fn read_symbol(&self, br: &mut LosslessBitReader<'_>) -> Result<u16, DecoderError> {
158        if let Some(symbol) = self.single_symbol {
159            return Ok(symbol);
160        }
161
162        let mut code = 0u16;
163        for bits in 1..=self.max_len {
164            code |= (br.read_bit()? as u16) << (bits - 1);
165            if let Some(&symbol) = self.by_len[bits].get(&code) {
166                return Ok(symbol);
167            }
168        }
169
170        Err(DecoderError::Bitstream("invalid VP8L Huffman symbol"))
171    }
172}
173
174#[derive(Debug, Clone)]
175struct ColorCache {
176    colors: Vec<u32>,
177    hash_shift: u32,
178}
179
180impl ColorCache {
181    fn new(hash_bits: usize) -> Result<Self, DecoderError> {
182        if !(1..=MAX_CACHE_BITS).contains(&hash_bits) {
183            return Err(DecoderError::Bitstream("invalid VP8L color cache size"));
184        }
185        let size = 1usize << hash_bits;
186        Ok(Self {
187            colors: vec![0; size],
188            hash_shift: (32 - hash_bits) as u32,
189        })
190    }
191
192    fn insert(&mut self, argb: u32) {
193        let key = ((argb.wrapping_mul(COLOR_CACHE_HASH_MUL)) >> self.hash_shift) as usize;
194        self.colors[key] = argb;
195    }
196
197    fn lookup(&self, key: usize) -> Result<u32, DecoderError> {
198        self.colors
199            .get(key)
200            .copied()
201            .ok_or(DecoderError::Bitstream("invalid VP8L color cache lookup"))
202    }
203}
204
205#[derive(Debug, Clone, Copy, PartialEq, Eq)]
206enum TransformType {
207    Predictor,
208    CrossColor,
209    SubtractGreen,
210    ColorIndexing,
211}
212
213#[derive(Debug, Clone)]
214struct Transform {
215    kind: TransformType,
216    bits: usize,
217    xsize: usize,
218    ysize: usize,
219    data: Vec<u32>,
220}
221
222#[derive(Debug, Clone)]
223struct HTreeGroup {
224    green: HuffmanTree,
225    red: HuffmanTree,
226    blue: HuffmanTree,
227    alpha: HuffmanTree,
228    dist: HuffmanTree,
229}
230
231#[derive(Debug, Clone)]
232struct HuffmanMetadata {
233    huffman_subsample_bits: usize,
234    huffman_xsize: usize,
235    huffman_image: Option<Vec<usize>>,
236    groups: Vec<HTreeGroup>,
237}
238
239impl HuffmanMetadata {
240    fn group_index(&self, x: usize, y: usize) -> usize {
241        if let Some(image) = &self.huffman_image {
242            image[(y >> self.huffman_subsample_bits) * self.huffman_xsize
243                + (x >> self.huffman_subsample_bits)]
244        } else {
245            0
246        }
247    }
248}
249
250struct LosslessDecoder<'a> {
251    br: LosslessBitReader<'a>,
252}
253
254impl<'a> LosslessDecoder<'a> {
255    fn new(data: &'a [u8]) -> Self {
256        Self {
257            br: LosslessBitReader::new(data),
258        }
259    }
260
261    fn decode_image_stream(
262        &mut self,
263        xsize: usize,
264        ysize: usize,
265        top_level: bool,
266    ) -> Result<Vec<u32>, DecoderError> {
267        let mut transforms = Vec::new();
268        let mut transform_xsize = xsize;
269        let transform_ysize = ysize;
270
271        if top_level {
272            let mut transforms_seen = 0u32;
273            while self.br.read_bit()? == 1 {
274                let transform =
275                    self.read_transform(transform_xsize, transform_ysize, &mut transforms_seen)?;
276                if matches!(transform.kind, TransformType::ColorIndexing) {
277                    transform_xsize = subsample_size(transform_xsize, transform.bits);
278                }
279                transforms.push(transform);
280            }
281        }
282
283        let color_cache_bits = if self.br.read_bit()? == 1 {
284            let bits = self.br.read_bits(4)? as usize;
285            if !(1..=MAX_CACHE_BITS).contains(&bits) {
286                return Err(DecoderError::Bitstream("invalid VP8L color cache bits"));
287            }
288            bits
289        } else {
290            0
291        };
292
293        let metadata = self.read_huffman_codes(
294            transform_xsize,
295            transform_ysize,
296            color_cache_bits,
297            top_level,
298        )?;
299        let mut data = self.decode_image_data(
300            transform_xsize,
301            transform_ysize,
302            color_cache_bits,
303            &metadata,
304        )?;
305
306        if top_level {
307            for transform in transforms.iter().rev() {
308                data = apply_inverse_transform(transform, &data)?;
309            }
310        }
311
312        Ok(data)
313    }
314
315    fn read_transform(
316        &mut self,
317        xsize: usize,
318        ysize: usize,
319        transforms_seen: &mut u32,
320    ) -> Result<Transform, DecoderError> {
321        let type_bits = self.br.read_bits(2)? as usize;
322        let kind = match type_bits {
323            0 => TransformType::Predictor,
324            1 => TransformType::CrossColor,
325            2 => TransformType::SubtractGreen,
326            3 => TransformType::ColorIndexing,
327            _ => unreachable!(),
328        };
329
330        if (*transforms_seen & (1u32 << type_bits)) != 0 {
331            return Err(DecoderError::Bitstream("duplicate VP8L transform"));
332        }
333        *transforms_seen |= 1u32 << type_bits;
334
335        match kind {
336            TransformType::Predictor | TransformType::CrossColor => {
337                let bits = MIN_TRANSFORM_BITS + self.br.read_bits(NUM_TRANSFORM_BITS)? as usize;
338                let data = self.decode_image_stream(
339                    subsample_size(xsize, bits),
340                    subsample_size(ysize, bits),
341                    false,
342                )?;
343                Ok(Transform {
344                    kind,
345                    bits,
346                    xsize,
347                    ysize,
348                    data,
349                })
350            }
351            TransformType::SubtractGreen => Ok(Transform {
352                kind,
353                bits: 0,
354                xsize,
355                ysize,
356                data: Vec::new(),
357            }),
358            TransformType::ColorIndexing => {
359                let num_colors = self.br.read_bits(8)? as usize + 1;
360                let bits = if num_colors > 16 {
361                    0
362                } else if num_colors > 4 {
363                    1
364                } else if num_colors > 2 {
365                    2
366                } else {
367                    3
368                };
369                let palette = self.decode_image_stream(num_colors, 1, false)?;
370                let expanded = expand_color_map(&palette, num_colors, bits);
371                Ok(Transform {
372                    kind,
373                    bits,
374                    xsize,
375                    ysize,
376                    data: expanded,
377                })
378            }
379        }
380    }
381
382    fn read_huffman_codes(
383        &mut self,
384        xsize: usize,
385        ysize: usize,
386        color_cache_bits: usize,
387        allow_meta: bool,
388    ) -> Result<HuffmanMetadata, DecoderError> {
389        let mut huffman_subsample_bits = 0usize;
390        let mut huffman_xsize = 0usize;
391        let mut huffman_image = None;
392        let mapping = if allow_meta && self.br.read_bit()? == 1 {
393            huffman_subsample_bits =
394                MIN_HUFFMAN_BITS + self.br.read_bits(NUM_HUFFMAN_BITS)? as usize;
395            huffman_xsize = subsample_size(xsize, huffman_subsample_bits);
396            let huffman_ysize = subsample_size(ysize, huffman_subsample_bits);
397            let image = self.decode_image_stream(huffman_xsize, huffman_ysize, false)?;
398
399            let mut max_group = 0usize;
400            let raw_groups = image
401                .iter()
402                .map(|&pixel| ((pixel >> 8) & 0xffff) as usize)
403                .inspect(|&group| max_group = max_group.max(group))
404                .collect::<Vec<_>>();
405            let mut mapping = vec![None; max_group + 1];
406            let mut dense_image = Vec::with_capacity(raw_groups.len());
407            let mut next_group = 0usize;
408            for group in raw_groups {
409                let dense = if let Some(index) = mapping[group] {
410                    index
411                } else {
412                    let index = next_group;
413                    mapping[group] = Some(index);
414                    next_group += 1;
415                    index
416                };
417                dense_image.push(dense);
418            }
419            huffman_image = Some(dense_image);
420            mapping
421        } else {
422            vec![Some(0)]
423        };
424
425        let num_groups = mapping.iter().flatten().count();
426        let mut groups = vec![None; num_groups];
427        for dense in mapping {
428            let group = self.read_htree_group(color_cache_bits)?;
429            if let Some(index) = dense {
430                groups[index] = Some(group);
431            }
432        }
433
434        let groups = groups
435            .into_iter()
436            .map(|group| group.ok_or(DecoderError::Bitstream("missing VP8L Huffman group")))
437            .collect::<Result<Vec<_>, _>>()?;
438
439        Ok(HuffmanMetadata {
440            huffman_subsample_bits,
441            huffman_xsize,
442            huffman_image,
443            groups,
444        })
445    }
446
447    fn read_htree_group(&mut self, color_cache_bits: usize) -> Result<HTreeGroup, DecoderError> {
448        let green_alphabet_size = NUM_LITERAL_CODES
449            + NUM_LENGTH_CODES
450            + if color_cache_bits > 0 {
451                1usize << color_cache_bits
452            } else {
453                0
454            };
455
456        Ok(HTreeGroup {
457            green: self.read_huffman_code(green_alphabet_size)?,
458            red: self.read_huffman_code(NUM_LITERAL_CODES)?,
459            blue: self.read_huffman_code(NUM_LITERAL_CODES)?,
460            alpha: self.read_huffman_code(NUM_LITERAL_CODES)?,
461            dist: self.read_huffman_code(NUM_DISTANCE_CODES)?,
462        })
463    }
464
465    fn read_huffman_code(&mut self, alphabet_size: usize) -> Result<HuffmanTree, DecoderError> {
466        let mut code_lengths = vec![0u8; alphabet_size];
467        let simple_code = self.br.read_bit()? == 1;
468
469        if simple_code {
470            let num_symbols = self.br.read_bit()? as usize + 1;
471            let first_symbol_len_code = self.br.read_bit()? as usize;
472            let first_bits = if first_symbol_len_code == 0 { 1 } else { 8 };
473            let first_symbol = self.br.read_bits(first_bits)? as usize;
474            if first_symbol >= alphabet_size {
475                return Err(DecoderError::Bitstream(
476                    "invalid VP8L simple Huffman symbol",
477                ));
478            }
479            code_lengths[first_symbol] = 1;
480            if num_symbols == 2 {
481                let second_symbol = self.br.read_bits(8)? as usize;
482                if second_symbol >= alphabet_size {
483                    return Err(DecoderError::Bitstream(
484                        "invalid VP8L simple Huffman symbol",
485                    ));
486                }
487                code_lengths[second_symbol] = 1;
488            }
489        } else {
490            let mut code_length_code_lengths = [0u8; NUM_CODE_LENGTH_CODES];
491            let num_codes = self.br.read_bits(4)? as usize + 4;
492            if num_codes > NUM_CODE_LENGTH_CODES {
493                return Err(DecoderError::Bitstream("too many VP8L code length codes"));
494            }
495            for i in 0..num_codes {
496                code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] = self.br.read_bits(3)? as u8;
497            }
498            let code_length_tree = HuffmanTree::from_code_lengths(&code_length_code_lengths)?;
499            self.read_huffman_code_lengths(&code_length_tree, &mut code_lengths)?;
500        }
501
502        HuffmanTree::from_code_lengths(&code_lengths)
503    }
504
505    fn read_huffman_code_lengths(
506        &mut self,
507        code_length_tree: &HuffmanTree,
508        code_lengths: &mut [u8],
509    ) -> Result<(), DecoderError> {
510        let num_symbols = code_lengths.len();
511        let mut max_symbol = if self.br.read_bit()? == 1 {
512            let length_nbits = 2 + 2 * self.br.read_bits(3)? as usize;
513            let value = 2 + self.br.read_bits(length_nbits)? as usize;
514            if value > num_symbols {
515                return Err(DecoderError::Bitstream(
516                    "invalid VP8L Huffman code length span",
517                ));
518            }
519            value
520        } else {
521            num_symbols
522        };
523
524        let mut symbol = 0usize;
525        let mut prev_code_len = DEFAULT_CODE_LENGTH;
526        while symbol < num_symbols {
527            if max_symbol == 0 {
528                break;
529            }
530            max_symbol -= 1;
531
532            let code_len = code_length_tree.read_symbol(&mut self.br)? as usize;
533            if code_len < CODE_LENGTH_REPEAT_CODE {
534                code_lengths[symbol] = code_len as u8;
535                if code_len != 0 {
536                    prev_code_len = code_len as u8;
537                }
538                symbol += 1;
539                continue;
540            }
541
542            let slot = code_len
543                .checked_sub(CODE_LENGTH_REPEAT_CODE)
544                .ok_or(DecoderError::Bitstream("invalid VP8L repeat code"))?;
545            if slot >= CODE_LENGTH_EXTRA_BITS.len() {
546                return Err(DecoderError::Bitstream("invalid VP8L repeat code"));
547            }
548            let repeat = self.br.read_bits(CODE_LENGTH_EXTRA_BITS[slot])? as usize
549                + CODE_LENGTH_REPEAT_OFFSETS[slot];
550            if symbol + repeat > num_symbols {
551                return Err(DecoderError::Bitstream("VP8L repeat overruns code lengths"));
552            }
553            let value = if code_len == CODE_LENGTH_REPEAT_CODE {
554                prev_code_len
555            } else {
556                0
557            };
558            for len in &mut code_lengths[symbol..symbol + repeat] {
559                *len = value;
560            }
561            symbol += repeat;
562        }
563
564        Ok(())
565    }
566
567    fn decode_image_data(
568        &mut self,
569        width: usize,
570        height: usize,
571        color_cache_bits: usize,
572        metadata: &HuffmanMetadata,
573    ) -> Result<Vec<u32>, DecoderError> {
574        let mut data = vec![0u32; width * height];
575        let mut color_cache = if color_cache_bits > 0 {
576            Some(ColorCache::new(color_cache_bits)?)
577        } else {
578            None
579        };
580        let mut pos = 0usize;
581        let len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
582        let color_cache_limit = len_code_limit
583            + if color_cache_bits > 0 {
584                1usize << color_cache_bits
585            } else {
586                0
587            };
588
589        while pos < data.len() {
590            let x = pos % width;
591            let y = pos / width;
592            let group = &metadata.groups[metadata.group_index(x, y)];
593            let code = group.green.read_symbol(&mut self.br)? as usize;
594
595            if code < NUM_LITERAL_CODES {
596                let red = group.red.read_symbol(&mut self.br)? as u32;
597                let blue = group.blue.read_symbol(&mut self.br)? as u32;
598                let alpha = group.alpha.read_symbol(&mut self.br)? as u32;
599                let pixel = (alpha << 24) | (red << 16) | ((code as u32) << 8) | blue;
600                data[pos] = pixel;
601                if let Some(cache) = &mut color_cache {
602                    cache.insert(pixel);
603                }
604                pos += 1;
605            } else if code < len_code_limit {
606                let length = get_copy_value(code - NUM_LITERAL_CODES, &mut self.br)?;
607                let dist_symbol = group.dist.read_symbol(&mut self.br)? as usize;
608                let dist_code = get_copy_value(dist_symbol, &mut self.br)?;
609                let dist = plane_code_to_distance(width, dist_code);
610                if dist > pos || pos + length > data.len() {
611                    return Err(DecoderError::Bitstream("invalid VP8L backward reference"));
612                }
613                for i in 0..length {
614                    let pixel = data[pos + i - dist];
615                    data[pos + i] = pixel;
616                    if let Some(cache) = &mut color_cache {
617                        cache.insert(pixel);
618                    }
619                }
620                pos += length;
621            } else if code < color_cache_limit {
622                let key = code - len_code_limit;
623                let cache = color_cache
624                    .as_mut()
625                    .ok_or(DecoderError::Bitstream("unexpected VP8L color cache code"))?;
626                let pixel = cache.lookup(key)?;
627                data[pos] = pixel;
628                cache.insert(pixel);
629                pos += 1;
630            } else {
631                return Err(DecoderError::Bitstream("invalid VP8L green Huffman symbol"));
632            }
633        }
634
635        Ok(data)
636    }
637}
638
639fn reverse_bits(mut code: u32, bits: usize) -> u16 {
640    let mut out = 0u32;
641    for _ in 0..bits {
642        out = (out << 1) | (code & 1);
643        code >>= 1;
644    }
645    out as u16
646}
647
648fn subsample_size(size: usize, bits: usize) -> usize {
649    (size + (1usize << bits) - 1) >> bits
650}
651
652fn get_copy_value(symbol: usize, br: &mut LosslessBitReader<'_>) -> Result<usize, DecoderError> {
653    if symbol < 4 {
654        Ok(symbol + 1)
655    } else {
656        let extra_bits = (symbol - 2) >> 1;
657        let offset = (2 + (symbol & 1)) << extra_bits;
658        Ok(offset + br.read_bits(extra_bits)? as usize + 1)
659    }
660}
661
662fn plane_code_to_distance(width: usize, plane_code: usize) -> usize {
663    if plane_code > CODE_TO_PLANE.len() {
664        plane_code - CODE_TO_PLANE.len()
665    } else {
666        let dist_code = CODE_TO_PLANE[plane_code - 1];
667        let y_offset = (dist_code >> 4) as isize;
668        let x_offset = 8isize - (dist_code & 0x0f) as isize;
669        let dist = y_offset * width as isize + x_offset;
670        dist.max(1) as usize
671    }
672}
673
674fn add_pixels(a: u32, b: u32) -> u32 {
675    let alpha = (((a >> 24) as u8).wrapping_add((b >> 24) as u8)) as u32;
676    let red = (((a >> 16) as u8).wrapping_add((b >> 16) as u8)) as u32;
677    let green = (((a >> 8) as u8).wrapping_add((b >> 8) as u8)) as u32;
678    let blue = ((a as u8).wrapping_add(b as u8)) as u32;
679    (alpha << 24) | (red << 16) | (green << 8) | blue
680}
681
682fn average2(a: u32, b: u32) -> u32 {
683    (((a ^ b) & 0xfefe_fefeu32) >> 1) + (a & b)
684}
685
686fn clip255(value: i32) -> u32 {
687    value.clamp(0, 255) as u32
688}
689
690fn clamped_add_subtract_full(left: u32, top: u32, top_left: u32) -> u32 {
691    let alpha = clip255((left >> 24) as i32 + (top >> 24) as i32 - (top_left >> 24) as i32);
692    let red = clip255(
693        ((left >> 16) & 0xff) as i32 + ((top >> 16) & 0xff) as i32
694            - ((top_left >> 16) & 0xff) as i32,
695    );
696    let green = clip255(
697        ((left >> 8) & 0xff) as i32 + ((top >> 8) & 0xff) as i32 - ((top_left >> 8) & 0xff) as i32,
698    );
699    let blue = clip255((left & 0xff) as i32 + (top & 0xff) as i32 - (top_left & 0xff) as i32);
700    (alpha << 24) | (red << 16) | (green << 8) | blue
701}
702
703fn clamped_add_subtract_half(left: u32, top: u32, top_left: u32) -> u32 {
704    let avg = average2(left, top);
705    let alpha = clip255((avg >> 24) as i32 + ((avg >> 24) as i32 - (top_left >> 24) as i32) / 2);
706    let red = clip255(
707        ((avg >> 16) & 0xff) as i32
708            + (((avg >> 16) & 0xff) as i32 - ((top_left >> 16) & 0xff) as i32) / 2,
709    );
710    let green = clip255(
711        ((avg >> 8) & 0xff) as i32
712            + (((avg >> 8) & 0xff) as i32 - ((top_left >> 8) & 0xff) as i32) / 2,
713    );
714    let blue = clip255((avg & 0xff) as i32 + ((avg & 0xff) as i32 - (top_left & 0xff) as i32) / 2);
715    (alpha << 24) | (red << 16) | (green << 8) | blue
716}
717
718fn select_predictor(left: u32, top: u32, top_left: u32) -> u32 {
719    let pred_alpha = ((left >> 24) as i32) + ((top >> 24) as i32) - ((top_left >> 24) as i32);
720    let pred_red = ((left >> 16) & 0xff) as i32 + ((top >> 16) & 0xff) as i32
721        - ((top_left >> 16) & 0xff) as i32;
722    let pred_green =
723        ((left >> 8) & 0xff) as i32 + ((top >> 8) & 0xff) as i32 - ((top_left >> 8) & 0xff) as i32;
724    let pred_blue = (left & 0xff) as i32 + (top & 0xff) as i32 - (top_left & 0xff) as i32;
725
726    let left_distance = (pred_alpha - ((left >> 24) as i32)).abs()
727        + (pred_red - (((left >> 16) & 0xff) as i32)).abs()
728        + (pred_green - (((left >> 8) & 0xff) as i32)).abs()
729        + (pred_blue - ((left & 0xff) as i32)).abs();
730    let top_distance = (pred_alpha - ((top >> 24) as i32)).abs()
731        + (pred_red - (((top >> 16) & 0xff) as i32)).abs()
732        + (pred_green - (((top >> 8) & 0xff) as i32)).abs()
733        + (pred_blue - ((top & 0xff) as i32)).abs();
734
735    if left_distance < top_distance {
736        left
737    } else {
738        top
739    }
740}
741
742fn predictor(mode: u8, left: u32, top: u32, top_left: u32, top_right: u32) -> u32 {
743    match mode {
744        0 | 14 | 15 => ARGB_BLACK,
745        1 => left,
746        2 => top,
747        3 => top_right,
748        4 => top_left,
749        5 => average2(average2(left, top_right), top),
750        6 => average2(left, top_left),
751        7 => average2(left, top),
752        8 => average2(top_left, top),
753        9 => average2(top, top_right),
754        10 => average2(average2(left, top_left), average2(top, top_right)),
755        11 => select_predictor(left, top, top_left),
756        12 => clamped_add_subtract_full(left, top, top_left),
757        13 => clamped_add_subtract_half(left, top, top_left),
758        _ => ARGB_BLACK,
759    }
760}
761
762fn color_transform_delta(transform: u8, color: u8) -> i32 {
763    ((transform as i8 as i32) * (color as i8 as i32)) >> 5
764}
765
766fn expand_color_map(palette: &[u32], num_colors: usize, bits: usize) -> Vec<u32> {
767    let final_num_colors = 1usize << (8 >> bits);
768    let mut expanded = vec![0u32; final_num_colors];
769    if num_colors == 0 {
770        return expanded;
771    }
772
773    expanded[0] = palette[0];
774    for i in 1..num_colors {
775        expanded[i] = add_pixels(palette[i], expanded[i - 1]);
776    }
777    expanded
778}
779
780fn apply_inverse_transform(transform: &Transform, input: &[u32]) -> Result<Vec<u32>, DecoderError> {
781    match transform.kind {
782        TransformType::SubtractGreen => Ok(input
783            .iter()
784            .map(|&argb| {
785                let green = (argb >> 8) & 0xff;
786                let red = (((argb >> 16) & 0xff) + green) & 0xff;
787                let blue = ((argb & 0xff) + green) & 0xff;
788                (argb & 0xff00_ff00) | (red << 16) | blue
789            })
790            .collect()),
791        TransformType::CrossColor => {
792            let expected_len = transform
793                .xsize
794                .checked_mul(transform.ysize)
795                .ok_or(DecoderError::Bitstream("VP8L transform size overflow"))?;
796            if input.len() != expected_len {
797                return Err(DecoderError::Bitstream("VP8L cross-color size mismatch"));
798            }
799            let tiles_per_row = subsample_size(transform.xsize, transform.bits);
800            let mut output = vec![0u32; input.len()];
801            for y in 0..transform.ysize {
802                for x in 0..transform.xsize {
803                    let argb = input[y * transform.xsize + x];
804                    let code = transform.data
805                        [(y >> transform.bits) * tiles_per_row + (x >> transform.bits)];
806                    let green_to_red = code as u8;
807                    let green_to_blue = ((code >> 8) & 0xff) as u8;
808                    let red_to_blue = ((code >> 16) & 0xff) as u8;
809                    let green = ((argb >> 8) & 0xff) as u8;
810                    let mut red = ((argb >> 16) & 0xff) as i32;
811                    let mut blue = (argb & 0xff) as i32;
812                    red = (red + color_transform_delta(green_to_red, green)) & 0xff;
813                    blue = (blue + color_transform_delta(green_to_blue, green)) & 0xff;
814                    blue = (blue + color_transform_delta(red_to_blue, red as u8)) & 0xff;
815                    output[y * transform.xsize + x] =
816                        (argb & 0xff00_ff00) | ((red as u32) << 16) | (blue as u32);
817                }
818            }
819            Ok(output)
820        }
821        TransformType::Predictor => {
822            let expected_len = transform
823                .xsize
824                .checked_mul(transform.ysize)
825                .ok_or(DecoderError::Bitstream("VP8L transform size overflow"))?;
826            if input.len() != expected_len {
827                return Err(DecoderError::Bitstream("VP8L predictor size mismatch"));
828            }
829            let tiles_per_row = subsample_size(transform.xsize, transform.bits);
830            let mut output = vec![0u32; input.len()];
831            for y in 0..transform.ysize {
832                for x in 0..transform.xsize {
833                    let residual = input[y * transform.xsize + x];
834                    let pred = if y == 0 {
835                        if x == 0 {
836                            ARGB_BLACK
837                        } else {
838                            output[y * transform.xsize + x - 1]
839                        }
840                    } else if x == 0 {
841                        output[(y - 1) * transform.xsize]
842                    } else {
843                        let left = output[y * transform.xsize + x - 1];
844                        let top = output[(y - 1) * transform.xsize + x];
845                        let top_left = output[(y - 1) * transform.xsize + x - 1];
846                        let top_right = if x + 1 < transform.xsize {
847                            output[(y - 1) * transform.xsize + x + 1]
848                        } else {
849                            output[y * transform.xsize]
850                        };
851                        let mode = ((transform.data
852                            [(y >> transform.bits) * tiles_per_row + (x >> transform.bits)]
853                            >> 8)
854                            & 0x0f) as u8;
855                        predictor(mode, left, top, top_left, top_right)
856                    };
857                    output[y * transform.xsize + x] = add_pixels(residual, pred);
858                }
859            }
860            Ok(output)
861        }
862        TransformType::ColorIndexing => {
863            let reduced_width = subsample_size(transform.xsize, transform.bits);
864            let expected_len = reduced_width
865                .checked_mul(transform.ysize)
866                .ok_or(DecoderError::Bitstream("VP8L transform size overflow"))?;
867            if input.len() != expected_len {
868                return Err(DecoderError::Bitstream("VP8L color indexing size mismatch"));
869            }
870
871            let bits_per_pixel = 8 >> transform.bits;
872            let pixels_per_byte = 1usize << transform.bits;
873            let bit_mask = (1u32 << bits_per_pixel) - 1;
874            let mut output = vec![0u32; transform.xsize * transform.ysize];
875
876            if transform.bits == 0 {
877                for (dst, &src) in output.iter_mut().zip(input.iter()) {
878                    let index = ((src >> 8) & 0xff) as usize;
879                    *dst = transform.data.get(index).copied().unwrap_or(0);
880                }
881                return Ok(output);
882            }
883
884            for y in 0..transform.ysize {
885                let src_row = &input[y * reduced_width..(y + 1) * reduced_width];
886                let dst_row = &mut output[y * transform.xsize..(y + 1) * transform.xsize];
887                let mut x = 0usize;
888                for &packed in src_row {
889                    let mut indices = (packed >> 8) & 0xff;
890                    for _ in 0..pixels_per_byte {
891                        if x >= transform.xsize {
892                            break;
893                        }
894                        let index = (indices & bit_mask) as usize;
895                        dst_row[x] = transform.data.get(index).copied().unwrap_or(0);
896                        indices >>= bits_per_pixel;
897                        x += 1;
898                    }
899                }
900            }
901
902            Ok(output)
903        }
904    }
905}
906
907fn argb_to_rgba(argb: &[u32]) -> Vec<u8> {
908    let mut rgba = vec![0u8; argb.len() * 4];
909    for (index, &pixel) in argb.iter().enumerate() {
910        let base = index * 4;
911        rgba[base] = ((pixel >> 16) & 0xff) as u8;
912        rgba[base + 1] = ((pixel >> 8) & 0xff) as u8;
913        rgba[base + 2] = (pixel & 0xff) as u8;
914        rgba[base + 3] = (pixel >> 24) as u8;
915    }
916    rgba
917}
918
919pub(crate) fn decode_lossless_vp8l_to_argb(
920    data: &[u8],
921) -> Result<(usize, usize, Vec<u32>), DecoderError> {
922    let info = get_lossless_info(data)?;
923    let bitstream = data
924        .get(5..)
925        .ok_or(DecoderError::NotEnoughData("VP8L frame payload"))?;
926    let mut decoder = LosslessDecoder::new(bitstream);
927    let argb = decoder.decode_image_stream(info.width, info.height, true)?;
928    if argb.len() != info.width * info.height {
929        return Err(DecoderError::Bitstream("decoded VP8L image has wrong size"));
930    }
931    Ok((info.width, info.height, argb))
932}
933
934/// Decodes a raw `VP8L` frame payload to RGBA.
935pub fn decode_lossless_vp8l_to_rgba(data: &[u8]) -> Result<DecodedImage, DecoderError> {
936    let (width, height, argb) = decode_lossless_vp8l_to_argb(data)?;
937
938    Ok(DecodedImage {
939        width,
940        height,
941        rgba: argb_to_rgba(&argb),
942    })
943}
944
945/// Decodes a still lossless WebP container to RGBA.
946pub fn decode_lossless_webp_to_rgba(data: &[u8]) -> Result<DecodedImage, DecoderError> {
947    let parsed = parse_still_webp(data)?;
948    if parsed.features.format != WebpFormat::Lossless {
949        return Err(DecoderError::Unsupported(
950            "expected a still lossless WebP image",
951        ));
952    }
953    decode_lossless_vp8l_to_rgba(parsed.image_data)
954}