1 | //! Decoding of lossless WebP images |
2 | //! |
3 | //! [Lossless spec](https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification) |
4 | //! |
5 | |
6 | use std::{ |
7 | error, fmt, |
8 | io::Read, |
9 | ops::{AddAssign, Shl}, |
10 | }; |
11 | |
12 | use byteorder::ReadBytesExt; |
13 | |
14 | use crate::{error::DecodingError, ImageError, ImageFormat, ImageResult}; |
15 | |
16 | use super::huffman::HuffmanTree; |
17 | use super::lossless_transform::{add_pixels, TransformType}; |
18 | |
19 | const CODE_LENGTH_CODES: usize = 19; |
20 | const CODE_LENGTH_CODE_ORDER: [usize; CODE_LENGTH_CODES] = [ |
21 | 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, |
22 | ]; |
23 | |
24 | #[rustfmt::skip] |
25 | const DISTANCE_MAP: [(i8, i8); 120] = [ |
26 | (0, 1), (1, 0), (1, 1), (-1, 1), (0, 2), (2, 0), (1, 2), (-1, 2), |
27 | (2, 1), (-2, 1), (2, 2), (-2, 2), (0, 3), (3, 0), (1, 3), (-1, 3), |
28 | (3, 1), (-3, 1), (2, 3), (-2, 3), (3, 2), (-3, 2), (0, 4), (4, 0), |
29 | (1, 4), (-1, 4), (4, 1), (-4, 1), (3, 3), (-3, 3), (2, 4), (-2, 4), |
30 | (4, 2), (-4, 2), (0, 5), (3, 4), (-3, 4), (4, 3), (-4, 3), (5, 0), |
31 | (1, 5), (-1, 5), (5, 1), (-5, 1), (2, 5), (-2, 5), (5, 2), (-5, 2), |
32 | (4, 4), (-4, 4), (3, 5), (-3, 5), (5, 3), (-5, 3), (0, 6), (6, 0), |
33 | (1, 6), (-1, 6), (6, 1), (-6, 1), (2, 6), (-2, 6), (6, 2), (-6, 2), |
34 | (4, 5), (-4, 5), (5, 4), (-5, 4), (3, 6), (-3, 6), (6, 3), (-6, 3), |
35 | (0, 7), (7, 0), (1, 7), (-1, 7), (5, 5), (-5, 5), (7, 1), (-7, 1), |
36 | (4, 6), (-4, 6), (6, 4), (-6, 4), (2, 7), (-2, 7), (7, 2), (-7, 2), |
37 | (3, 7), (-3, 7), (7, 3), (-7, 3), (5, 6), (-5, 6), (6, 5), (-6, 5), |
38 | (8, 0), (4, 7), (-4, 7), (7, 4), (-7, 4), (8, 1), (8, 2), (6, 6), |
39 | (-6, 6), (8, 3), (5, 7), (-5, 7), (7, 5), (-7, 5), (8, 4), (6, 7), |
40 | (-6, 7), (7, 6), (-7, 6), (8, 5), (7, 7), (-7, 7), (8, 6), (8, 7) |
41 | ]; |
42 | |
43 | const GREEN: usize = 0; |
44 | const RED: usize = 1; |
45 | const BLUE: usize = 2; |
46 | const ALPHA: usize = 3; |
47 | const DIST: usize = 4; |
48 | |
49 | const HUFFMAN_CODES_PER_META_CODE: usize = 5; |
50 | |
51 | type HuffmanCodeGroup = [HuffmanTree; HUFFMAN_CODES_PER_META_CODE]; |
52 | |
53 | const ALPHABET_SIZE: [u16; HUFFMAN_CODES_PER_META_CODE] = [256 + 24, 256, 256, 256, 40]; |
54 | |
55 | #[inline ] |
56 | pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 { |
57 | ((u32::from(size) + (1u32 << bits) - 1) >> bits) |
58 | .try_into() |
59 | .unwrap() |
60 | } |
61 | |
62 | #[derive (Debug, Clone, Copy)] |
63 | pub(crate) enum DecoderError { |
64 | /// Signature of 0x2f not found |
65 | LosslessSignatureInvalid(u8), |
66 | /// Version Number must be 0 |
67 | VersionNumberInvalid(u8), |
68 | |
69 | /// |
70 | InvalidColorCacheBits(u8), |
71 | |
72 | HuffmanError, |
73 | |
74 | BitStreamError, |
75 | |
76 | TransformError, |
77 | } |
78 | |
79 | impl fmt::Display for DecoderError { |
80 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
81 | match self { |
82 | DecoderError::LosslessSignatureInvalid(sig: &u8) => { |
83 | f.write_fmt(format_args!("Invalid lossless signature: {}" , sig)) |
84 | } |
85 | DecoderError::VersionNumberInvalid(num: &u8) => { |
86 | f.write_fmt(format_args!("Invalid version number: {}" , num)) |
87 | } |
88 | DecoderError::InvalidColorCacheBits(num: &u8) => f.write_fmt(format_args!( |
89 | "Invalid color cache(must be between 1-11): {}" , |
90 | num |
91 | )), |
92 | DecoderError::HuffmanError => f.write_fmt(format_args!("Error building Huffman Tree" )), |
93 | DecoderError::BitStreamError => { |
94 | f.write_fmt(format_args!("Error while reading bitstream" )) |
95 | } |
96 | DecoderError::TransformError => { |
97 | f.write_fmt(format_args!("Error while reading or writing transforms" )) |
98 | } |
99 | } |
100 | } |
101 | } |
102 | |
103 | impl From<DecoderError> for ImageError { |
104 | fn from(e: DecoderError) -> ImageError { |
105 | ImageError::Decoding(DecodingError::new(format:ImageFormat::WebP.into(), err:e)) |
106 | } |
107 | } |
108 | |
109 | impl error::Error for DecoderError {} |
110 | |
111 | const NUM_TRANSFORM_TYPES: usize = 4; |
112 | |
113 | //Decodes lossless WebP images |
114 | #[derive (Debug)] |
115 | pub(crate) struct LosslessDecoder<R> { |
116 | r: R, |
117 | bit_reader: BitReader, |
118 | frame: LosslessFrame, |
119 | transforms: [Option<TransformType>; NUM_TRANSFORM_TYPES], |
120 | transform_order: Vec<u8>, |
121 | } |
122 | |
123 | impl<R: Read> LosslessDecoder<R> { |
124 | /// Create a new decoder |
125 | pub(crate) fn new(r: R) -> LosslessDecoder<R> { |
126 | LosslessDecoder { |
127 | r, |
128 | bit_reader: BitReader::new(), |
129 | frame: Default::default(), |
130 | transforms: [None, None, None, None], |
131 | transform_order: Vec::new(), |
132 | } |
133 | } |
134 | |
135 | /// Reads the frame |
136 | pub(crate) fn decode_frame(&mut self) -> ImageResult<&LosslessFrame> { |
137 | let signature = self.r.read_u8()?; |
138 | |
139 | if signature != 0x2f { |
140 | return Err(DecoderError::LosslessSignatureInvalid(signature).into()); |
141 | } |
142 | |
143 | let mut buf = Vec::new(); |
144 | self.r.read_to_end(&mut buf)?; |
145 | self.bit_reader.init(buf); |
146 | |
147 | self.frame.width = self.bit_reader.read_bits::<u16>(14)? + 1; |
148 | self.frame.height = self.bit_reader.read_bits::<u16>(14)? + 1; |
149 | |
150 | let _alpha_used = self.bit_reader.read_bits::<u8>(1)?; |
151 | |
152 | let version_num = self.bit_reader.read_bits::<u8>(3)?; |
153 | |
154 | if version_num != 0 { |
155 | return Err(DecoderError::VersionNumberInvalid(version_num).into()); |
156 | } |
157 | |
158 | let mut data = self.decode_image_stream(self.frame.width, self.frame.height, true)?; |
159 | |
160 | for &trans_index in self.transform_order.iter().rev() { |
161 | let trans = self.transforms[usize::from(trans_index)].as_ref().unwrap(); |
162 | trans.apply_transform(&mut data, self.frame.width, self.frame.height)?; |
163 | } |
164 | |
165 | self.frame.buf = data; |
166 | Ok(&self.frame) |
167 | } |
168 | |
169 | //used for alpha data in extended decoding |
170 | pub(crate) fn decode_frame_implicit_dims( |
171 | &mut self, |
172 | width: u16, |
173 | height: u16, |
174 | ) -> ImageResult<&LosslessFrame> { |
175 | let mut buf = Vec::new(); |
176 | self.r.read_to_end(&mut buf)?; |
177 | self.bit_reader.init(buf); |
178 | |
179 | self.frame.width = width; |
180 | self.frame.height = height; |
181 | |
182 | let mut data = self.decode_image_stream(self.frame.width, self.frame.height, true)?; |
183 | |
184 | //transform_order is vector of indices(0-3) into transforms in order decoded |
185 | for &trans_index in self.transform_order.iter().rev() { |
186 | let trans = self.transforms[usize::from(trans_index)].as_ref().unwrap(); |
187 | trans.apply_transform(&mut data, self.frame.width, self.frame.height)?; |
188 | } |
189 | |
190 | self.frame.buf = data; |
191 | Ok(&self.frame) |
192 | } |
193 | |
194 | /// Reads Image data from the bitstream |
195 | /// Can be in any of the 5 roles described in the Specification |
196 | /// ARGB Image role has different behaviour to the other 4 |
197 | /// xsize and ysize describe the size of the blocks where each block has its own entropy code |
198 | fn decode_image_stream( |
199 | &mut self, |
200 | xsize: u16, |
201 | ysize: u16, |
202 | is_argb_img: bool, |
203 | ) -> ImageResult<Vec<u32>> { |
204 | let trans_xsize = if is_argb_img { |
205 | self.read_transforms()? |
206 | } else { |
207 | xsize |
208 | }; |
209 | |
210 | let color_cache_bits = self.read_color_cache()?; |
211 | |
212 | let color_cache = color_cache_bits.map(|bits| { |
213 | let size = 1 << bits; |
214 | let cache = vec![0u32; size]; |
215 | ColorCache { |
216 | color_cache_bits: bits, |
217 | color_cache: cache, |
218 | } |
219 | }); |
220 | |
221 | let huffman_info = self.read_huffman_codes(is_argb_img, trans_xsize, ysize, color_cache)?; |
222 | |
223 | //decode data |
224 | let data = self.decode_image_data(trans_xsize, ysize, huffman_info)?; |
225 | |
226 | Ok(data) |
227 | } |
228 | |
229 | /// Reads transforms and their data from the bitstream |
230 | fn read_transforms(&mut self) -> ImageResult<u16> { |
231 | let mut xsize = self.frame.width; |
232 | |
233 | while self.bit_reader.read_bits::<u8>(1)? == 1 { |
234 | let transform_type_val = self.bit_reader.read_bits::<u8>(2)?; |
235 | |
236 | if self.transforms[usize::from(transform_type_val)].is_some() { |
237 | //can only have one of each transform, error |
238 | return Err(DecoderError::TransformError.into()); |
239 | } |
240 | |
241 | self.transform_order.push(transform_type_val); |
242 | |
243 | let transform_type = match transform_type_val { |
244 | 0 => { |
245 | //predictor |
246 | |
247 | let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2; |
248 | |
249 | let block_xsize = subsample_size(xsize, size_bits); |
250 | let block_ysize = subsample_size(self.frame.height, size_bits); |
251 | |
252 | let data = self.decode_image_stream(block_xsize, block_ysize, false)?; |
253 | |
254 | TransformType::PredictorTransform { |
255 | size_bits, |
256 | predictor_data: data, |
257 | } |
258 | } |
259 | 1 => { |
260 | //color transform |
261 | |
262 | let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2; |
263 | |
264 | let block_xsize = subsample_size(xsize, size_bits); |
265 | let block_ysize = subsample_size(self.frame.height, size_bits); |
266 | |
267 | let data = self.decode_image_stream(block_xsize, block_ysize, false)?; |
268 | |
269 | TransformType::ColorTransform { |
270 | size_bits, |
271 | transform_data: data, |
272 | } |
273 | } |
274 | 2 => { |
275 | //subtract green |
276 | |
277 | TransformType::SubtractGreen |
278 | } |
279 | 3 => { |
280 | let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1; |
281 | |
282 | let mut color_map = self.decode_image_stream(color_table_size, 1, false)?; |
283 | |
284 | let bits = if color_table_size <= 2 { |
285 | 3 |
286 | } else if color_table_size <= 4 { |
287 | 2 |
288 | } else if color_table_size <= 16 { |
289 | 1 |
290 | } else { |
291 | 0 |
292 | }; |
293 | xsize = subsample_size(xsize, bits); |
294 | |
295 | Self::adjust_color_map(&mut color_map); |
296 | |
297 | TransformType::ColorIndexingTransform { |
298 | table_size: color_table_size, |
299 | table_data: color_map, |
300 | } |
301 | } |
302 | _ => unreachable!(), |
303 | }; |
304 | |
305 | self.transforms[usize::from(transform_type_val)] = Some(transform_type); |
306 | } |
307 | |
308 | Ok(xsize) |
309 | } |
310 | |
311 | /// Adjusts the color map since it's subtraction coded |
312 | fn adjust_color_map(color_map: &mut [u32]) { |
313 | for i in 1..color_map.len() { |
314 | color_map[i] = add_pixels(color_map[i], color_map[i - 1]); |
315 | } |
316 | } |
317 | |
318 | /// Reads huffman codes associated with an image |
319 | fn read_huffman_codes( |
320 | &mut self, |
321 | read_meta: bool, |
322 | xsize: u16, |
323 | ysize: u16, |
324 | color_cache: Option<ColorCache>, |
325 | ) -> ImageResult<HuffmanInfo> { |
326 | let mut num_huff_groups = 1; |
327 | |
328 | let mut huffman_bits = 0; |
329 | let mut huffman_xsize = 1; |
330 | let mut huffman_ysize = 1; |
331 | let mut entropy_image = Vec::new(); |
332 | |
333 | if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 { |
334 | //meta huffman codes |
335 | huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2; |
336 | huffman_xsize = subsample_size(xsize, huffman_bits); |
337 | huffman_ysize = subsample_size(ysize, huffman_bits); |
338 | |
339 | entropy_image = self.decode_image_stream(huffman_xsize, huffman_ysize, false)?; |
340 | |
341 | for pixel in entropy_image.iter_mut() { |
342 | let meta_huff_code = (*pixel >> 8) & 0xffff; |
343 | |
344 | *pixel = meta_huff_code; |
345 | |
346 | if meta_huff_code >= num_huff_groups { |
347 | num_huff_groups = meta_huff_code + 1; |
348 | } |
349 | } |
350 | } |
351 | |
352 | let mut hufftree_groups = Vec::new(); |
353 | |
354 | for _i in 0..num_huff_groups { |
355 | let mut group: HuffmanCodeGroup = Default::default(); |
356 | for j in 0..HUFFMAN_CODES_PER_META_CODE { |
357 | let mut alphabet_size = ALPHABET_SIZE[j]; |
358 | if j == 0 { |
359 | if let Some(color_cache) = color_cache.as_ref() { |
360 | alphabet_size += 1 << color_cache.color_cache_bits; |
361 | } |
362 | } |
363 | |
364 | let tree = self.read_huffman_code(alphabet_size)?; |
365 | group[j] = tree; |
366 | } |
367 | hufftree_groups.push(group); |
368 | } |
369 | |
370 | let huffman_mask = if huffman_bits == 0 { |
371 | !0 |
372 | } else { |
373 | (1 << huffman_bits) - 1 |
374 | }; |
375 | |
376 | let info = HuffmanInfo { |
377 | xsize: huffman_xsize, |
378 | _ysize: huffman_ysize, |
379 | color_cache, |
380 | image: entropy_image, |
381 | bits: huffman_bits, |
382 | mask: huffman_mask, |
383 | huffman_code_groups: hufftree_groups, |
384 | }; |
385 | |
386 | Ok(info) |
387 | } |
388 | |
389 | /// Decodes and returns a single huffman tree |
390 | fn read_huffman_code(&mut self, alphabet_size: u16) -> ImageResult<HuffmanTree> { |
391 | let simple = self.bit_reader.read_bits::<u8>(1)? == 1; |
392 | |
393 | if simple { |
394 | let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1; |
395 | |
396 | let mut code_lengths = vec![u16::from(num_symbols - 1)]; |
397 | let mut codes = vec![0]; |
398 | let mut symbols = Vec::new(); |
399 | |
400 | let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?; |
401 | symbols.push(self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?); |
402 | |
403 | if num_symbols == 2 { |
404 | symbols.push(self.bit_reader.read_bits::<u16>(8)?); |
405 | code_lengths.push(1); |
406 | codes.push(1); |
407 | } |
408 | |
409 | HuffmanTree::build_explicit(code_lengths, codes, symbols) |
410 | } else { |
411 | let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES]; |
412 | |
413 | let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?; |
414 | for i in 0..num_code_lengths { |
415 | code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] = |
416 | self.bit_reader.read_bits(3)?; |
417 | } |
418 | |
419 | let new_code_lengths = |
420 | self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?; |
421 | |
422 | HuffmanTree::build_implicit(new_code_lengths) |
423 | } |
424 | } |
425 | |
426 | /// Reads huffman code lengths |
427 | fn read_huffman_code_lengths( |
428 | &mut self, |
429 | code_length_code_lengths: Vec<u16>, |
430 | num_symbols: u16, |
431 | ) -> ImageResult<Vec<u16>> { |
432 | let table = HuffmanTree::build_implicit(code_length_code_lengths)?; |
433 | |
434 | let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 { |
435 | let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?; |
436 | 2 + self.bit_reader.read_bits::<u16>(length_nbits)? |
437 | } else { |
438 | num_symbols |
439 | }; |
440 | |
441 | let mut code_lengths = vec![0; usize::from(num_symbols)]; |
442 | let mut prev_code_len = 8; //default code length |
443 | |
444 | let mut symbol = 0; |
445 | while symbol < num_symbols { |
446 | if max_symbol == 0 { |
447 | break; |
448 | } |
449 | max_symbol -= 1; |
450 | |
451 | let code_len = table.read_symbol(&mut self.bit_reader)?; |
452 | |
453 | if code_len < 16 { |
454 | code_lengths[usize::from(symbol)] = code_len; |
455 | symbol += 1; |
456 | if code_len != 0 { |
457 | prev_code_len = code_len; |
458 | } |
459 | } else { |
460 | let use_prev = code_len == 16; |
461 | let slot = code_len - 16; |
462 | let extra_bits = match slot { |
463 | 0 => 2, |
464 | 1 => 3, |
465 | 2 => 7, |
466 | _ => return Err(DecoderError::BitStreamError.into()), |
467 | }; |
468 | let repeat_offset = match slot { |
469 | 0 | 1 => 3, |
470 | 2 => 11, |
471 | _ => return Err(DecoderError::BitStreamError.into()), |
472 | }; |
473 | |
474 | let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset; |
475 | |
476 | if symbol + repeat > num_symbols { |
477 | return Err(DecoderError::BitStreamError.into()); |
478 | } else { |
479 | let length = if use_prev { prev_code_len } else { 0 }; |
480 | while repeat > 0 { |
481 | repeat -= 1; |
482 | code_lengths[usize::from(symbol)] = length; |
483 | symbol += 1; |
484 | } |
485 | } |
486 | } |
487 | } |
488 | |
489 | Ok(code_lengths) |
490 | } |
491 | |
492 | /// Decodes the image data using the huffman trees and either of the 3 methods of decoding |
493 | fn decode_image_data( |
494 | &mut self, |
495 | width: u16, |
496 | height: u16, |
497 | mut huffman_info: HuffmanInfo, |
498 | ) -> ImageResult<Vec<u32>> { |
499 | let num_values = usize::from(width) * usize::from(height); |
500 | let mut data = vec![0; num_values]; |
501 | |
502 | let huff_index = huffman_info.get_huff_index(0, 0); |
503 | let mut tree = &huffman_info.huffman_code_groups[huff_index]; |
504 | let mut last_cached = 0; |
505 | let mut index = 0; |
506 | let mut x = 0; |
507 | let mut y = 0; |
508 | while index < num_values { |
509 | if (x & huffman_info.mask) == 0 { |
510 | let index = huffman_info.get_huff_index(x, y); |
511 | tree = &huffman_info.huffman_code_groups[index]; |
512 | } |
513 | |
514 | let code = tree[GREEN].read_symbol(&mut self.bit_reader)?; |
515 | |
516 | //check code |
517 | if code < 256 { |
518 | //literal, so just use huffman codes and read as argb |
519 | let red = tree[RED].read_symbol(&mut self.bit_reader)?; |
520 | let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?; |
521 | let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?; |
522 | |
523 | data[index] = (u32::from(alpha) << 24) |
524 | + (u32::from(red) << 16) |
525 | + (u32::from(code) << 8) |
526 | + u32::from(blue); |
527 | |
528 | index += 1; |
529 | x += 1; |
530 | if x >= width { |
531 | x = 0; |
532 | y += 1; |
533 | } |
534 | } else if code < 256 + 24 { |
535 | //backward reference, so go back and use that to add image data |
536 | let length_symbol = code - 256; |
537 | let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?; |
538 | |
539 | let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?; |
540 | let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?; |
541 | let dist = Self::plane_code_to_distance(width, dist_code); |
542 | |
543 | if index < dist || num_values - index < length { |
544 | return Err(DecoderError::BitStreamError.into()); |
545 | } |
546 | |
547 | for i in 0..length { |
548 | data[index + i] = data[index + i - dist]; |
549 | } |
550 | index += length; |
551 | x += u16::try_from(length).unwrap(); |
552 | while x >= width { |
553 | x -= width; |
554 | y += 1; |
555 | } |
556 | if index < num_values { |
557 | let index = huffman_info.get_huff_index(x, y); |
558 | tree = &huffman_info.huffman_code_groups[index]; |
559 | } |
560 | } else { |
561 | //color cache, so use previously stored pixels to get this pixel |
562 | let key = code - 256 - 24; |
563 | |
564 | if let Some(color_cache) = huffman_info.color_cache.as_mut() { |
565 | //cache old colors |
566 | while last_cached < index { |
567 | color_cache.insert(data[last_cached]); |
568 | last_cached += 1; |
569 | } |
570 | data[index] = color_cache.lookup(key.into())?; |
571 | } else { |
572 | return Err(DecoderError::BitStreamError.into()); |
573 | } |
574 | index += 1; |
575 | x += 1; |
576 | if x >= width { |
577 | x = 0; |
578 | y += 1; |
579 | } |
580 | } |
581 | } |
582 | |
583 | Ok(data) |
584 | } |
585 | |
586 | /// Reads color cache data from the bitstream |
587 | fn read_color_cache(&mut self) -> ImageResult<Option<u8>> { |
588 | if self.bit_reader.read_bits::<u8>(1)? == 1 { |
589 | let code_bits = self.bit_reader.read_bits::<u8>(4)?; |
590 | |
591 | if !(1..=11).contains(&code_bits) { |
592 | return Err(DecoderError::InvalidColorCacheBits(code_bits).into()); |
593 | } |
594 | |
595 | Ok(Some(code_bits)) |
596 | } else { |
597 | Ok(None) |
598 | } |
599 | } |
600 | |
601 | /// Gets the copy distance from the prefix code and bitstream |
602 | fn get_copy_distance(bit_reader: &mut BitReader, prefix_code: u16) -> ImageResult<usize> { |
603 | if prefix_code < 4 { |
604 | return Ok(usize::from(prefix_code + 1)); |
605 | } |
606 | let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap(); |
607 | let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits; |
608 | |
609 | Ok(offset + bit_reader.read_bits::<usize>(extra_bits)? + 1) |
610 | } |
611 | |
612 | /// Gets distance to pixel |
613 | fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize { |
614 | if plane_code > 120 { |
615 | plane_code - 120 |
616 | } else { |
617 | let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1]; |
618 | |
619 | let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize); |
620 | if dist < 1 { |
621 | return 1; |
622 | } |
623 | dist.try_into().unwrap() |
624 | } |
625 | } |
626 | } |
627 | |
628 | #[derive (Debug, Clone)] |
629 | struct HuffmanInfo { |
630 | xsize: u16, |
631 | _ysize: u16, |
632 | color_cache: Option<ColorCache>, |
633 | image: Vec<u32>, |
634 | bits: u8, |
635 | mask: u16, |
636 | huffman_code_groups: Vec<HuffmanCodeGroup>, |
637 | } |
638 | |
639 | impl HuffmanInfo { |
640 | fn get_huff_index(&self, x: u16, y: u16) -> usize { |
641 | if self.bits == 0 { |
642 | return 0; |
643 | } |
644 | let position: usize = usize::from((y >> self.bits) * self.xsize + (x >> self.bits)); |
645 | let meta_huff_code: usize = self.image[position].try_into().unwrap(); |
646 | meta_huff_code |
647 | } |
648 | } |
649 | |
650 | #[derive (Debug, Clone)] |
651 | struct ColorCache { |
652 | color_cache_bits: u8, |
653 | color_cache: Vec<u32>, |
654 | } |
655 | |
656 | impl ColorCache { |
657 | fn insert(&mut self, color: u32) { |
658 | let index: u32 = (0x1e35a7bdu32.overflowing_mul(color).0) >> (32 - self.color_cache_bits); |
659 | self.color_cache[index as usize] = color; |
660 | } |
661 | |
662 | fn lookup(&self, index: usize) -> ImageResult<u32> { |
663 | match self.color_cache.get(index) { |
664 | Some(&value: u32) => Ok(value), |
665 | None => Err(DecoderError::BitStreamError.into()), |
666 | } |
667 | } |
668 | } |
669 | |
670 | #[derive (Debug, Clone)] |
671 | pub(crate) struct BitReader { |
672 | buf: Vec<u8>, |
673 | index: usize, |
674 | bit_count: u8, |
675 | } |
676 | |
677 | impl BitReader { |
678 | fn new() -> BitReader { |
679 | BitReader { |
680 | buf: Vec::new(), |
681 | index: 0, |
682 | bit_count: 0, |
683 | } |
684 | } |
685 | |
686 | fn init(&mut self, buf: Vec<u8>) { |
687 | self.buf = buf; |
688 | } |
689 | |
690 | pub(crate) fn read_bits<T>(&mut self, num: u8) -> ImageResult<T> |
691 | where |
692 | T: num_traits::Unsigned + Shl<u8, Output = T> + AddAssign<T> + From<bool>, |
693 | { |
694 | let mut value: T = T::zero(); |
695 | |
696 | for i in 0..num { |
697 | if self.buf.len() <= self.index { |
698 | return Err(DecoderError::BitStreamError.into()); |
699 | } |
700 | let bit_true = self.buf[self.index] & (1 << self.bit_count) != 0; |
701 | value += T::from(bit_true) << i; |
702 | self.bit_count = if self.bit_count == 7 { |
703 | self.index += 1; |
704 | 0 |
705 | } else { |
706 | self.bit_count + 1 |
707 | }; |
708 | } |
709 | |
710 | Ok(value) |
711 | } |
712 | } |
713 | |
714 | #[derive (Debug, Clone, Default)] |
715 | pub(crate) struct LosslessFrame { |
716 | pub(crate) width: u16, |
717 | pub(crate) height: u16, |
718 | |
719 | pub(crate) buf: Vec<u32>, |
720 | } |
721 | |
722 | impl LosslessFrame { |
723 | /// Fills a buffer by converting from argb to rgba |
724 | pub(crate) fn fill_rgba(&self, buf: &mut [u8]) { |
725 | for (&argb_val: u32, chunk: &mut [u8]) in self.buf.iter().zip(buf.chunks_exact_mut(chunk_size:4)) { |
726 | chunk[0] = ((argb_val >> 16) & 0xff).try_into().unwrap(); |
727 | chunk[1] = ((argb_val >> 8) & 0xff).try_into().unwrap(); |
728 | chunk[2] = (argb_val & 0xff).try_into().unwrap(); |
729 | chunk[3] = ((argb_val >> 24) & 0xff).try_into().unwrap(); |
730 | } |
731 | } |
732 | |
733 | /// Get buffer size from the image |
734 | pub(crate) fn get_buf_size(&self) -> usize { |
735 | usize::from(self.width) * usize::from(self.height) * 4 |
736 | } |
737 | |
738 | /// Fills a buffer with just the green values from the lossless decoding |
739 | /// Used in extended alpha decoding |
740 | pub(crate) fn fill_green(&self, buf: &mut [u8]) { |
741 | for (&argb_val: u32, buf_value: &mut u8) in self.buf.iter().zip(buf.iter_mut()) { |
742 | *buf_value = ((argb_val >> 8) & 0xff).try_into().unwrap(); |
743 | } |
744 | } |
745 | } |
746 | |
747 | #[cfg (test)] |
748 | mod test { |
749 | |
750 | use super::BitReader; |
751 | |
752 | #[test ] |
753 | fn bit_read_test() { |
754 | let mut bit_reader = BitReader::new(); |
755 | |
756 | //10011100 01000001 11100001 |
757 | let buf = vec![0x9C, 0x41, 0xE1]; |
758 | |
759 | bit_reader.init(buf); |
760 | |
761 | assert_eq!(bit_reader.read_bits::<u8>(3).unwrap(), 4); //100 |
762 | assert_eq!(bit_reader.read_bits::<u8>(2).unwrap(), 3); //11 |
763 | assert_eq!(bit_reader.read_bits::<u8>(6).unwrap(), 12); //001100 |
764 | assert_eq!(bit_reader.read_bits::<u16>(10).unwrap(), 40); //0000101000 |
765 | assert_eq!(bit_reader.read_bits::<u8>(3).unwrap(), 7); //111 |
766 | } |
767 | |
768 | #[test ] |
769 | fn bit_read_error_test() { |
770 | let mut bit_reader = BitReader::new(); |
771 | |
772 | //01101010 |
773 | let buf = vec![0x6A]; |
774 | |
775 | bit_reader.init(buf); |
776 | |
777 | assert_eq!(bit_reader.read_bits::<u8>(3).unwrap(), 2); //010 |
778 | assert_eq!(bit_reader.read_bits::<u8>(5).unwrap(), 13); //01101 |
779 | assert!(bit_reader.read_bits::<u8>(4).is_err()); //error |
780 | } |
781 | } |
782 | |