1use std::collections::TryReserveError;
4use std::iter::repeat;
5
6#[inline(always)]
7pub(crate) fn expand_packed<F>(buf: &mut [u8], channels: usize, bit_depth: u8, mut func: F)
8where
9 F: FnMut(u8, &mut [u8]),
10{
11 let pixels = buf.len() / channels * bit_depth as usize;
12 let extra = pixels % 8;
13 let entries = pixels / 8
14 + match extra {
15 0 => 0,
16 _ => 1,
17 };
18 let mask = ((1u16 << bit_depth) - 1) as u8;
19 let i = (0..entries)
20 .rev() .flat_map(|idx|
22 (0..8/bit_depth).map(|i| i*bit_depth).zip(repeat(idx)))
24 .skip(extra);
25 let buf_len = buf.len();
26 let j_inv = (channels..buf_len).step_by(channels);
27 for ((shift, i), j_inv) in i.zip(j_inv) {
28 let j = buf_len - j_inv;
29 let pixel = (buf[i] & (mask << shift)) >> shift;
30 func(pixel, &mut buf[j..(j + channels)]);
31 }
32}
33
34#[allow(dead_code)]
37pub(crate) fn expand_bits(bit_depth: u8, row_size: u32, buf: &[u8]) -> Vec<u8> {
39 let mask = (1u8 << bit_depth as usize) - 1;
41 let scaling_factor = 255 / ((1 << bit_depth as usize) - 1);
42 let bit_width = row_size * u32::from(bit_depth);
43 let skip = if bit_width % 8 == 0 {
44 0
45 } else {
46 (8 - bit_width % 8) / u32::from(bit_depth)
47 };
48 let row_len = row_size + skip;
49 let mut p = Vec::new();
50 let mut i = 0;
51 for v in buf {
52 for shift_inv in 1..=8 / bit_depth {
53 let shift = 8 - bit_depth * shift_inv;
54 if i % (row_len as usize) < (row_size as usize) {
57 let pixel = (v & (mask << shift as usize)) >> shift as usize;
58 p.push(pixel * scaling_factor);
59 }
60 i += 1;
61 }
62 }
63 p
64}
65
66#[allow(dead_code)]
68pub(crate) fn check_dimension_overflow(width: u32, height: u32, bytes_per_pixel: u8) -> bool {
70 u64::from(width) * u64::from(height) > u64::MAX / u64::from(bytes_per_pixel)
71}
72
73#[allow(dead_code)]
74pub(crate) fn vec_copy_to_u8<T>(vec: &[T]) -> Vec<u8>
76where
77 T: bytemuck::Pod,
78{
79 bytemuck::cast_slice(vec).to_owned()
80}
81
82#[inline]
83pub(crate) fn clamp<N>(a: N, min: N, max: N) -> N
84where
85 N: PartialOrd,
86{
87 if a < min {
88 min
89 } else if a > max {
90 max
91 } else {
92 a
93 }
94}
95
96#[inline]
97pub(crate) fn vec_try_with_capacity<T>(capacity: usize) -> Result<Vec<T>, TryReserveError> {
98 let mut vec = Vec::new();
99 vec.try_reserve_exact(capacity)?;
100 Ok(vec)
101}
102
103#[cfg(test)]
104mod test {
105 #[test]
106 fn gray_to_luma8_skip() {
107 let check = |bit_depth, w, from, to| {
108 assert_eq!(super::expand_bits(bit_depth, w, from), to);
109 };
110 check(
112 1,
113 10,
114 &[0b11110000, 0b11000000, 0b00001111, 0b11000000],
115 vec![
116 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255,
117 ],
118 );
119 check(
121 2,
122 5,
123 &[0b11110000, 0b11000000, 0b00001111, 0b11000000],
124 vec![255, 255, 0, 0, 255, 0, 0, 255, 255, 255],
125 );
126 check(
128 2,
129 4,
130 &[0b11110000, 0b00001111],
131 vec![255, 255, 0, 0, 0, 0, 255, 255],
132 );
133 check(4, 1, &[0b11110011, 0b00001100], vec![255, 0]);
135 }
136}