aboutsummaryrefslogtreecommitdiff
path: root/vendor/image/src/codecs/webp/lossless.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/image/src/codecs/webp/lossless.rs')
-rw-r--r--vendor/image/src/codecs/webp/lossless.rs783
1 files changed, 0 insertions, 783 deletions
diff --git a/vendor/image/src/codecs/webp/lossless.rs b/vendor/image/src/codecs/webp/lossless.rs
deleted file mode 100644
index 7271eda..0000000
--- a/vendor/image/src/codecs/webp/lossless.rs
+++ /dev/null
@@ -1,783 +0,0 @@
-//! Decoding of lossless WebP images
-//!
-//! [Lossless spec](https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification)
-//!
-
-use std::{
- convert::TryFrom,
- convert::TryInto,
- error, fmt,
- io::Read,
- ops::{AddAssign, Shl},
-};
-
-use byteorder::ReadBytesExt;
-
-use crate::{error::DecodingError, ImageError, ImageFormat, ImageResult};
-
-use super::huffman::HuffmanTree;
-use super::lossless_transform::{add_pixels, TransformType};
-
-const CODE_LENGTH_CODES: usize = 19;
-const CODE_LENGTH_CODE_ORDER: [usize; CODE_LENGTH_CODES] = [
- 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
-];
-
-#[rustfmt::skip]
-const DISTANCE_MAP: [(i8, i8); 120] = [
- (0, 1), (1, 0), (1, 1), (-1, 1), (0, 2), (2, 0), (1, 2), (-1, 2),
- (2, 1), (-2, 1), (2, 2), (-2, 2), (0, 3), (3, 0), (1, 3), (-1, 3),
- (3, 1), (-3, 1), (2, 3), (-2, 3), (3, 2), (-3, 2), (0, 4), (4, 0),
- (1, 4), (-1, 4), (4, 1), (-4, 1), (3, 3), (-3, 3), (2, 4), (-2, 4),
- (4, 2), (-4, 2), (0, 5), (3, 4), (-3, 4), (4, 3), (-4, 3), (5, 0),
- (1, 5), (-1, 5), (5, 1), (-5, 1), (2, 5), (-2, 5), (5, 2), (-5, 2),
- (4, 4), (-4, 4), (3, 5), (-3, 5), (5, 3), (-5, 3), (0, 6), (6, 0),
- (1, 6), (-1, 6), (6, 1), (-6, 1), (2, 6), (-2, 6), (6, 2), (-6, 2),
- (4, 5), (-4, 5), (5, 4), (-5, 4), (3, 6), (-3, 6), (6, 3), (-6, 3),
- (0, 7), (7, 0), (1, 7), (-1, 7), (5, 5), (-5, 5), (7, 1), (-7, 1),
- (4, 6), (-4, 6), (6, 4), (-6, 4), (2, 7), (-2, 7), (7, 2), (-7, 2),
- (3, 7), (-3, 7), (7, 3), (-7, 3), (5, 6), (-5, 6), (6, 5), (-6, 5),
- (8, 0), (4, 7), (-4, 7), (7, 4), (-7, 4), (8, 1), (8, 2), (6, 6),
- (-6, 6), (8, 3), (5, 7), (-5, 7), (7, 5), (-7, 5), (8, 4), (6, 7),
- (-6, 7), (7, 6), (-7, 6), (8, 5), (7, 7), (-7, 7), (8, 6), (8, 7)
-];
-
-const GREEN: usize = 0;
-const RED: usize = 1;
-const BLUE: usize = 2;
-const ALPHA: usize = 3;
-const DIST: usize = 4;
-
-const HUFFMAN_CODES_PER_META_CODE: usize = 5;
-
-type HuffmanCodeGroup = [HuffmanTree; HUFFMAN_CODES_PER_META_CODE];
-
-const ALPHABET_SIZE: [u16; HUFFMAN_CODES_PER_META_CODE] = [256 + 24, 256, 256, 256, 40];
-
-#[inline]
-pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 {
- ((u32::from(size) + (1u32 << bits) - 1) >> bits)
- .try_into()
- .unwrap()
-}
-
-#[derive(Debug, Clone, Copy)]
-pub(crate) enum DecoderError {
- /// Signature of 0x2f not found
- LosslessSignatureInvalid(u8),
- /// Version Number must be 0
- VersionNumberInvalid(u8),
-
- ///
- InvalidColorCacheBits(u8),
-
- HuffmanError,
-
- BitStreamError,
-
- TransformError,
-}
-
-impl fmt::Display for DecoderError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- DecoderError::LosslessSignatureInvalid(sig) => {
- f.write_fmt(format_args!("Invalid lossless signature: {}", sig))
- }
- DecoderError::VersionNumberInvalid(num) => {
- f.write_fmt(format_args!("Invalid version number: {}", num))
- }
- DecoderError::InvalidColorCacheBits(num) => f.write_fmt(format_args!(
- "Invalid color cache(must be between 1-11): {}",
- num
- )),
- DecoderError::HuffmanError => f.write_fmt(format_args!("Error building Huffman Tree")),
- DecoderError::BitStreamError => {
- f.write_fmt(format_args!("Error while reading bitstream"))
- }
- DecoderError::TransformError => {
- f.write_fmt(format_args!("Error while reading or writing transforms"))
- }
- }
- }
-}
-
-impl From<DecoderError> for ImageError {
- fn from(e: DecoderError) -> ImageError {
- ImageError::Decoding(DecodingError::new(ImageFormat::WebP.into(), e))
- }
-}
-
-impl error::Error for DecoderError {}
-
-const NUM_TRANSFORM_TYPES: usize = 4;
-
-//Decodes lossless WebP images
-#[derive(Debug)]
-pub(crate) struct LosslessDecoder<R> {
- r: R,
- bit_reader: BitReader,
- frame: LosslessFrame,
- transforms: [Option<TransformType>; NUM_TRANSFORM_TYPES],
- transform_order: Vec<u8>,
-}
-
-impl<R: Read> LosslessDecoder<R> {
- /// Create a new decoder
- pub(crate) fn new(r: R) -> LosslessDecoder<R> {
- LosslessDecoder {
- r,
- bit_reader: BitReader::new(),
- frame: Default::default(),
- transforms: [None, None, None, None],
- transform_order: Vec::new(),
- }
- }
-
- /// Reads the frame
- pub(crate) fn decode_frame(&mut self) -> ImageResult<&LosslessFrame> {
- let signature = self.r.read_u8()?;
-
- if signature != 0x2f {
- return Err(DecoderError::LosslessSignatureInvalid(signature).into());
- }
-
- let mut buf = Vec::new();
- self.r.read_to_end(&mut buf)?;
- self.bit_reader.init(buf);
-
- self.frame.width = self.bit_reader.read_bits::<u16>(14)? + 1;
- self.frame.height = self.bit_reader.read_bits::<u16>(14)? + 1;
-
- let _alpha_used = self.bit_reader.read_bits::<u8>(1)?;
-
- let version_num = self.bit_reader.read_bits::<u8>(3)?;
-
- if version_num != 0 {
- return Err(DecoderError::VersionNumberInvalid(version_num).into());
- }
-
- let mut data = self.decode_image_stream(self.frame.width, self.frame.height, true)?;
-
- for &trans_index in self.transform_order.iter().rev() {
- let trans = self.transforms[usize::from(trans_index)].as_ref().unwrap();
- trans.apply_transform(&mut data, self.frame.width, self.frame.height)?;
- }
-
- self.frame.buf = data;
- Ok(&self.frame)
- }
-
- //used for alpha data in extended decoding
- pub(crate) fn decode_frame_implicit_dims(
- &mut self,
- width: u16,
- height: u16,
- ) -> ImageResult<&LosslessFrame> {
- let mut buf = Vec::new();
- self.r.read_to_end(&mut buf)?;
- self.bit_reader.init(buf);
-
- self.frame.width = width;
- self.frame.height = height;
-
- let mut data = self.decode_image_stream(self.frame.width, self.frame.height, true)?;
-
- //transform_order is vector of indices(0-3) into transforms in order decoded
- for &trans_index in self.transform_order.iter().rev() {
- let trans = self.transforms[usize::from(trans_index)].as_ref().unwrap();
- trans.apply_transform(&mut data, self.frame.width, self.frame.height)?;
- }
-
- self.frame.buf = data;
- Ok(&self.frame)
- }
-
- /// Reads Image data from the bitstream
- /// Can be in any of the 5 roles described in the Specification
- /// ARGB Image role has different behaviour to the other 4
- /// xsize and ysize describe the size of the blocks where each block has its own entropy code
- fn decode_image_stream(
- &mut self,
- xsize: u16,
- ysize: u16,
- is_argb_img: bool,
- ) -> ImageResult<Vec<u32>> {
- let trans_xsize = if is_argb_img {
- self.read_transforms()?
- } else {
- xsize
- };
-
- let color_cache_bits = self.read_color_cache()?;
-
- let color_cache = color_cache_bits.map(|bits| {
- let size = 1 << bits;
- let cache = vec![0u32; size];
- ColorCache {
- color_cache_bits: bits,
- color_cache: cache,
- }
- });
-
- let huffman_info = self.read_huffman_codes(is_argb_img, trans_xsize, ysize, color_cache)?;
-
- //decode data
- let data = self.decode_image_data(trans_xsize, ysize, huffman_info)?;
-
- Ok(data)
- }
-
- /// Reads transforms and their data from the bitstream
- fn read_transforms(&mut self) -> ImageResult<u16> {
- let mut xsize = self.frame.width;
-
- while self.bit_reader.read_bits::<u8>(1)? == 1 {
- let transform_type_val = self.bit_reader.read_bits::<u8>(2)?;
-
- if self.transforms[usize::from(transform_type_val)].is_some() {
- //can only have one of each transform, error
- return Err(DecoderError::TransformError.into());
- }
-
- self.transform_order.push(transform_type_val);
-
- let transform_type = match transform_type_val {
- 0 => {
- //predictor
-
- let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
-
- let block_xsize = subsample_size(xsize, size_bits);
- let block_ysize = subsample_size(self.frame.height, size_bits);
-
- let data = self.decode_image_stream(block_xsize, block_ysize, false)?;
-
- TransformType::PredictorTransform {
- size_bits,
- predictor_data: data,
- }
- }
- 1 => {
- //color transform
-
- let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
-
- let block_xsize = subsample_size(xsize, size_bits);
- let block_ysize = subsample_size(self.frame.height, size_bits);
-
- let data = self.decode_image_stream(block_xsize, block_ysize, false)?;
-
- TransformType::ColorTransform {
- size_bits,
- transform_data: data,
- }
- }
- 2 => {
- //subtract green
-
- TransformType::SubtractGreen
- }
- 3 => {
- let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1;
-
- let mut color_map = self.decode_image_stream(color_table_size, 1, false)?;
-
- let bits = if color_table_size <= 2 {
- 3
- } else if color_table_size <= 4 {
- 2
- } else if color_table_size <= 16 {
- 1
- } else {
- 0
- };
- xsize = subsample_size(xsize, bits);
-
- Self::adjust_color_map(&mut color_map);
-
- TransformType::ColorIndexingTransform {
- table_size: color_table_size,
- table_data: color_map,
- }
- }
- _ => unreachable!(),
- };
-
- self.transforms[usize::from(transform_type_val)] = Some(transform_type);
- }
-
- Ok(xsize)
- }
-
- /// Adjusts the color map since it's subtraction coded
- fn adjust_color_map(color_map: &mut Vec<u32>) {
- for i in 1..color_map.len() {
- color_map[i] = add_pixels(color_map[i], color_map[i - 1]);
- }
- }
-
- /// Reads huffman codes associated with an image
- fn read_huffman_codes(
- &mut self,
- read_meta: bool,
- xsize: u16,
- ysize: u16,
- color_cache: Option<ColorCache>,
- ) -> ImageResult<HuffmanInfo> {
- let mut num_huff_groups = 1;
-
- let mut huffman_bits = 0;
- let mut huffman_xsize = 1;
- let mut huffman_ysize = 1;
- let mut entropy_image = Vec::new();
-
- if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 {
- //meta huffman codes
- huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
- huffman_xsize = subsample_size(xsize, huffman_bits);
- huffman_ysize = subsample_size(ysize, huffman_bits);
-
- entropy_image = self.decode_image_stream(huffman_xsize, huffman_ysize, false)?;
-
- for pixel in entropy_image.iter_mut() {
- let meta_huff_code = (*pixel >> 8) & 0xffff;
-
- *pixel = meta_huff_code;
-
- if meta_huff_code >= num_huff_groups {
- num_huff_groups = meta_huff_code + 1;
- }
- }
- }
-
- let mut hufftree_groups = Vec::new();
-
- for _i in 0..num_huff_groups {
- let mut group: HuffmanCodeGroup = Default::default();
- for j in 0..HUFFMAN_CODES_PER_META_CODE {
- let mut alphabet_size = ALPHABET_SIZE[j];
- if j == 0 {
- if let Some(color_cache) = color_cache.as_ref() {
- alphabet_size += 1 << color_cache.color_cache_bits;
- }
- }
-
- let tree = self.read_huffman_code(alphabet_size)?;
- group[j] = tree;
- }
- hufftree_groups.push(group);
- }
-
- let huffman_mask = if huffman_bits == 0 {
- !0
- } else {
- (1 << huffman_bits) - 1
- };
-
- let info = HuffmanInfo {
- xsize: huffman_xsize,
- _ysize: huffman_ysize,
- color_cache,
- image: entropy_image,
- bits: huffman_bits,
- mask: huffman_mask,
- huffman_code_groups: hufftree_groups,
- };
-
- Ok(info)
- }
-
- /// Decodes and returns a single huffman tree
- fn read_huffman_code(&mut self, alphabet_size: u16) -> ImageResult<HuffmanTree> {
- let simple = self.bit_reader.read_bits::<u8>(1)? == 1;
-
- if simple {
- let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1;
-
- let mut code_lengths = vec![u16::from(num_symbols - 1)];
- let mut codes = vec![0];
- let mut symbols = Vec::new();
-
- let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?;
- symbols.push(self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?);
-
- if num_symbols == 2 {
- symbols.push(self.bit_reader.read_bits::<u16>(8)?);
- code_lengths.push(1);
- codes.push(1);
- }
-
- HuffmanTree::build_explicit(code_lengths, codes, symbols)
- } else {
- let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES];
-
- let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?;
- for i in 0..num_code_lengths {
- code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] =
- self.bit_reader.read_bits(3)?;
- }
-
- let new_code_lengths =
- self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?;
-
- HuffmanTree::build_implicit(new_code_lengths)
- }
- }
-
- /// Reads huffman code lengths
- fn read_huffman_code_lengths(
- &mut self,
- code_length_code_lengths: Vec<u16>,
- num_symbols: u16,
- ) -> ImageResult<Vec<u16>> {
- let table = HuffmanTree::build_implicit(code_length_code_lengths)?;
-
- let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 {
- let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?;
- 2 + self.bit_reader.read_bits::<u16>(length_nbits)?
- } else {
- num_symbols
- };
-
- let mut code_lengths = vec![0; usize::from(num_symbols)];
- let mut prev_code_len = 8; //default code length
-
- let mut symbol = 0;
- while symbol < num_symbols {
- if max_symbol == 0 {
- break;
- }
- max_symbol -= 1;
-
- let code_len = table.read_symbol(&mut self.bit_reader)?;
-
- if code_len < 16 {
- code_lengths[usize::from(symbol)] = code_len;
- symbol += 1;
- if code_len != 0 {
- prev_code_len = code_len;
- }
- } else {
- let use_prev = code_len == 16;
- let slot = code_len - 16;
- let extra_bits = match slot {
- 0 => 2,
- 1 => 3,
- 2 => 7,
- _ => return Err(DecoderError::BitStreamError.into()),
- };
- let repeat_offset = match slot {
- 0 | 1 => 3,
- 2 => 11,
- _ => return Err(DecoderError::BitStreamError.into()),
- };
-
- let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset;
-
- if symbol + repeat > num_symbols {
- return Err(DecoderError::BitStreamError.into());
- } else {
- let length = if use_prev { prev_code_len } else { 0 };
- while repeat > 0 {
- repeat -= 1;
- code_lengths[usize::from(symbol)] = length;
- symbol += 1;
- }
- }
- }
- }
-
- Ok(code_lengths)
- }
-
- /// Decodes the image data using the huffman trees and either of the 3 methods of decoding
- fn decode_image_data(
- &mut self,
- width: u16,
- height: u16,
- mut huffman_info: HuffmanInfo,
- ) -> ImageResult<Vec<u32>> {
- let num_values = usize::from(width) * usize::from(height);
- let mut data = vec![0; num_values];
-
- let huff_index = huffman_info.get_huff_index(0, 0);
- let mut tree = &huffman_info.huffman_code_groups[huff_index];
- let mut last_cached = 0;
- let mut index = 0;
- let mut x = 0;
- let mut y = 0;
- while index < num_values {
- if (x & huffman_info.mask) == 0 {
- let index = huffman_info.get_huff_index(x, y);
- tree = &huffman_info.huffman_code_groups[index];
- }
-
- let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
-
- //check code
- if code < 256 {
- //literal, so just use huffman codes and read as argb
- let red = tree[RED].read_symbol(&mut self.bit_reader)?;
- let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?;
- let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?;
-
- data[index] = (u32::from(alpha) << 24)
- + (u32::from(red) << 16)
- + (u32::from(code) << 8)
- + u32::from(blue);
-
- index += 1;
- x += 1;
- if x >= width {
- x = 0;
- y += 1;
- }
- } else if code < 256 + 24 {
- //backward reference, so go back and use that to add image data
- let length_symbol = code - 256;
- let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?;
-
- let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?;
- let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?;
- let dist = Self::plane_code_to_distance(width, dist_code);
-
- if index < dist || num_values - index < length {
- return Err(DecoderError::BitStreamError.into());
- }
-
- for i in 0..length {
- data[index + i] = data[index + i - dist];
- }
- index += length;
- x += u16::try_from(length).unwrap();
- while x >= width {
- x -= width;
- y += 1;
- }
- if index < num_values {
- let index = huffman_info.get_huff_index(x, y);
- tree = &huffman_info.huffman_code_groups[index];
- }
- } else {
- //color cache, so use previously stored pixels to get this pixel
- let key = code - 256 - 24;
-
- if let Some(color_cache) = huffman_info.color_cache.as_mut() {
- //cache old colors
- while last_cached < index {
- color_cache.insert(data[last_cached]);
- last_cached += 1;
- }
- data[index] = color_cache.lookup(key.into())?;
- } else {
- return Err(DecoderError::BitStreamError.into());
- }
- index += 1;
- x += 1;
- if x >= width {
- x = 0;
- y += 1;
- }
- }
- }
-
- Ok(data)
- }
-
- /// Reads color cache data from the bitstream
- fn read_color_cache(&mut self) -> ImageResult<Option<u8>> {
- if self.bit_reader.read_bits::<u8>(1)? == 1 {
- let code_bits = self.bit_reader.read_bits::<u8>(4)?;
-
- if !(1..=11).contains(&code_bits) {
- return Err(DecoderError::InvalidColorCacheBits(code_bits).into());
- }
-
- Ok(Some(code_bits))
- } else {
- Ok(None)
- }
- }
-
- /// Gets the copy distance from the prefix code and bitstream
- fn get_copy_distance(bit_reader: &mut BitReader, prefix_code: u16) -> ImageResult<usize> {
- if prefix_code < 4 {
- return Ok(usize::from(prefix_code + 1));
- }
- let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap();
- let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits;
-
- Ok(offset + bit_reader.read_bits::<usize>(extra_bits)? + 1)
- }
-
- /// Gets distance to pixel
- fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize {
- if plane_code > 120 {
- plane_code - 120
- } else {
- let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1];
-
- let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize);
- if dist < 1 {
- return 1;
- }
- dist.try_into().unwrap()
- }
- }
-}
-
-#[derive(Debug, Clone)]
-struct HuffmanInfo {
- xsize: u16,
- _ysize: u16,
- color_cache: Option<ColorCache>,
- image: Vec<u32>,
- bits: u8,
- mask: u16,
- huffman_code_groups: Vec<HuffmanCodeGroup>,
-}
-
-impl HuffmanInfo {
- fn get_huff_index(&self, x: u16, y: u16) -> usize {
- if self.bits == 0 {
- return 0;
- }
- let position = usize::from((y >> self.bits) * self.xsize + (x >> self.bits));
- let meta_huff_code: usize = self.image[position].try_into().unwrap();
- meta_huff_code
- }
-}
-
-#[derive(Debug, Clone)]
-struct ColorCache {
- color_cache_bits: u8,
- color_cache: Vec<u32>,
-}
-
-impl ColorCache {
- fn insert(&mut self, color: u32) {
- let index = (0x1e35a7bdu32.overflowing_mul(color).0) >> (32 - self.color_cache_bits);
- self.color_cache[index as usize] = color;
- }
-
- fn lookup(&self, index: usize) -> ImageResult<u32> {
- match self.color_cache.get(index) {
- Some(&value) => Ok(value),
- None => Err(DecoderError::BitStreamError.into()),
- }
- }
-}
-
-#[derive(Debug, Clone)]
-pub(crate) struct BitReader {
- buf: Vec<u8>,
- index: usize,
- bit_count: u8,
-}
-
-impl BitReader {
- fn new() -> BitReader {
- BitReader {
- buf: Vec::new(),
- index: 0,
- bit_count: 0,
- }
- }
-
- fn init(&mut self, buf: Vec<u8>) {
- self.buf = buf;
- }
-
- pub(crate) fn read_bits<T>(&mut self, num: u8) -> ImageResult<T>
- where
- T: num_traits::Unsigned + Shl<u8, Output = T> + AddAssign<T> + From<bool>,
- {
- let mut value: T = T::zero();
-
- for i in 0..num {
- if self.buf.len() <= self.index {
- return Err(DecoderError::BitStreamError.into());
- }
- let bit_true = self.buf[self.index] & (1 << self.bit_count) != 0;
- value += T::from(bit_true) << i;
- self.bit_count = if self.bit_count == 7 {
- self.index += 1;
- 0
- } else {
- self.bit_count + 1
- };
- }
-
- Ok(value)
- }
-}
-
-#[derive(Debug, Clone, Default)]
-pub(crate) struct LosslessFrame {
- pub(crate) width: u16,
- pub(crate) height: u16,
-
- pub(crate) buf: Vec<u32>,
-}
-
-impl LosslessFrame {
- /// Fills a buffer by converting from argb to rgba
- pub(crate) fn fill_rgba(&self, buf: &mut [u8]) {
- for (&argb_val, chunk) in self.buf.iter().zip(buf.chunks_exact_mut(4)) {
- chunk[0] = ((argb_val >> 16) & 0xff).try_into().unwrap();
- chunk[1] = ((argb_val >> 8) & 0xff).try_into().unwrap();
- chunk[2] = (argb_val & 0xff).try_into().unwrap();
- chunk[3] = ((argb_val >> 24) & 0xff).try_into().unwrap();
- }
- }
-
- /// Get buffer size from the image
- pub(crate) fn get_buf_size(&self) -> usize {
- usize::from(self.width) * usize::from(self.height) * 4
- }
-
- /// Fills a buffer with just the green values from the lossless decoding
- /// Used in extended alpha decoding
- pub(crate) fn fill_green(&self, buf: &mut [u8]) {
- for (&argb_val, buf_value) in self.buf.iter().zip(buf.iter_mut()) {
- *buf_value = ((argb_val >> 8) & 0xff).try_into().unwrap();
- }
- }
-}
-
-#[cfg(test)]
-mod test {
-
- use super::BitReader;
-
- #[test]
- fn bit_read_test() {
- let mut bit_reader = BitReader::new();
-
- //10011100 01000001 11100001
- let buf = vec![0x9C, 0x41, 0xE1];
-
- bit_reader.init(buf);
-
- assert_eq!(bit_reader.read_bits::<u8>(3).unwrap(), 4); //100
- assert_eq!(bit_reader.read_bits::<u8>(2).unwrap(), 3); //11
- assert_eq!(bit_reader.read_bits::<u8>(6).unwrap(), 12); //001100
- assert_eq!(bit_reader.read_bits::<u16>(10).unwrap(), 40); //0000101000
- assert_eq!(bit_reader.read_bits::<u8>(3).unwrap(), 7); //111
- }
-
- #[test]
- fn bit_read_error_test() {
- let mut bit_reader = BitReader::new();
-
- //01101010
- let buf = vec![0x6A];
-
- bit_reader.init(buf);
-
- assert_eq!(bit_reader.read_bits::<u8>(3).unwrap(), 2); //010
- assert_eq!(bit_reader.read_bits::<u8>(5).unwrap(), 13); //01101
- assert!(bit_reader.read_bits::<u8>(4).is_err()); //error
- }
-}