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