zune_image/core_filters/
depth.rs1use zune_core::bit_depth::{BitDepth, BitType};
30use zune_core::log::trace;
31
32use crate::channel::Channel;
33use crate::errors::ImageErrors;
34use crate::image::Image;
35use crate::traits::OperationsTrait;
36
37#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
49pub(crate) fn depth_u16_to_u8(from: &[u16], to: &mut [u8], max_value: u16) {
50 if max_value == u16::MAX {
51 for (old, new) in from.iter().zip(to.iter_mut()) {
53 let new_val = (old / 257) as u8;
54 *new = new_val;
55 }
56 } else {
57 let max = 1.0 / f32::from(max_value);
59 let scale = 255.0;
60
61 for (old, new) in from.iter().zip(to.iter_mut()) {
62 let new_val = ((f32::from(*old) * max) * scale) as u8;
63 *new = new_val;
64 }
65 }
66}
67
68#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
80pub(crate) fn depth_u8_to_u16(from: &[u8], to: &mut [u16], max_value: u16) {
81 let max = 1.0 / 255.0;
83 let scale = f32::from(max_value);
84
85 for (old, new) in from.iter().zip(to.iter_mut()) {
86 let new_val = ((f32::from(*old) * max) * scale) as u16;
87 *new = new_val;
88 }
89}
90
91#[derive(Copy, Clone)]
94pub struct Depth {
95 depth: BitDepth
96}
97
98impl Depth {
99 pub fn new(depth: BitDepth) -> Depth {
100 Depth { depth }
101 }
102}
103
104impl OperationsTrait for Depth {
105 fn name(&self) -> &'static str {
106 "Depth"
107 }
108
109 fn execute_impl(&self, image: &mut Image) -> Result<(), ImageErrors> {
110 let image_depth = image.depth();
111
112 if image_depth == self.depth {
113 trace!("Image depth already matches requested, no-op");
114 return Ok(());
115 }
116
117 for channel in image.channels_mut(false) {
118 match (image_depth, self.depth) {
119 (BitDepth::Eight, BitDepth::Sixteen) => {
120 let old_data = channel.reinterpret_as().unwrap();
121 let mut new_channel = Channel::new_with_length::<u16>(old_data.len() * 2);
122
123 let new_channel_raw = new_channel.reinterpret_as_mut().unwrap();
124
125 depth_u8_to_u16(old_data, new_channel_raw, self.depth.max_value());
126
127 *channel = new_channel;
128 }
129
130 (BitDepth::Sixteen, BitDepth::Eight) => {
131 let old_data = channel.reinterpret_as::<u16>().unwrap();
132 let mut new_channel = Channel::new_with_length::<u8>(channel.len() / 2);
133
134 let new_channel_raw = new_channel.reinterpret_as_mut().unwrap();
135
136 depth_u16_to_u8(old_data, new_channel_raw, image_depth.max_value());
137
138 *channel = new_channel;
139 }
140 (BitDepth::Float32, BitDepth::Eight) => {
141 let old_data = channel.reinterpret_as::<f32>().unwrap();
142 let mut new_channel = Channel::new_with_length::<u8>(channel.len() / 4);
143
144 let new_channel_raw = new_channel.reinterpret_as_mut::<u8>().unwrap();
145
146 for (old_chan, new_chan) in old_data.iter().zip(new_channel_raw.iter_mut()) {
148 *new_chan = (255.0 * old_chan).clamp(0.0, 255.0) as u8;
149 }
150
151 *channel = new_channel;
152 }
153 (BitDepth::Float32, BitDepth::Sixteen) => {
154 let old_data = channel.reinterpret_as::<f32>().unwrap();
155 let mut new_channel = Channel::new_with_length::<u16>(channel.len() / 2);
156
157 let new_channel_raw = new_channel.reinterpret_as_mut::<u16>().unwrap();
158
159 for (old_chan, new_chan) in old_data.iter().zip(new_channel_raw.iter_mut()) {
161 *new_chan = (65535.0 * old_chan).clamp(0.0, 65535.0) as u16;
162 }
163
164 *channel = new_channel;
165 }
166 (BitDepth::Eight, BitDepth::Float32) => {
167 let old_data = channel.reinterpret_as::<u8>().unwrap();
168 let mut new_channel = Channel::new_with_length::<f32>(old_data.len() * 4);
169
170 let new_channel_raw = new_channel.reinterpret_as_mut::<f32>().unwrap();
171
172 let recip = 1.0 / 255.0;
174 for (old_chan, new_chan) in old_data.iter().zip(new_channel_raw.iter_mut()) {
175 *new_chan = f32::from(*old_chan) * recip;
176 }
177
178 *channel = new_channel;
179 }
180 (BitDepth::Sixteen, BitDepth::Float32) => {
181 let old_data = channel.reinterpret_as::<u16>().unwrap();
182 let mut new_channel = Channel::new_with_length::<f32>(old_data.len() * 4);
183
184 let new_channel_raw = new_channel.reinterpret_as_mut::<f32>().unwrap();
185
186 let recip = 1.0 / 65535.0;
188
189 for (old_chan, new_chan) in old_data.iter().zip(new_channel_raw.iter_mut()) {
190 *new_chan = f32::from(*old_chan) * recip;
191 }
192
193 *channel = new_channel;
194 }
195
196 (_, _) => {
197 let msg = format!(
198 "Unknown depth conversion from {:?} to {:?}",
199 image_depth, self.depth
200 );
201
202 return Err(ImageErrors::GenericString(msg));
203 }
204 }
205 }
206 trace!("Image depth changed to {:?}", self.depth);
207
208 image.set_depth(self.depth);
209
210 Ok(())
211 }
212 fn supported_types(&self) -> &'static [BitType] {
213 &[BitType::U8, BitType::U16, BitType::F32]
214 }
215}