#[inline(always)]
fn f32_to_u8(y: f32) -> u8 {
(y.clamp(0.0, 1.0) * 255.0 + 0.5) as u8
}
#[inline(always)]
fn f32_to_u16(y: f32) -> u16 {
(y.clamp(0.0, 1.0) * 65535.0 + 0.5) as u16
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn grayf32_to_rgb_row<const BE: bool>(plane: &[f32], rgb_out: &mut [u8], width: usize) {
debug_assert!(plane.len() >= width, "plane too short");
debug_assert!(rgb_out.len() >= width * 3, "rgb_out too short");
for (x, &raw) in plane[..width].iter().enumerate() {
let y = if BE {
f32::from_bits(u32::from_be(raw.to_bits()))
} else {
f32::from_bits(u32::from_le(raw.to_bits()))
};
let v = f32_to_u8(y);
let i = x * 3;
rgb_out[i] = v;
rgb_out[i + 1] = v;
rgb_out[i + 2] = v;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn grayf32_to_rgba_row<const BE: bool>(
plane: &[f32],
rgba_out: &mut [u8],
width: usize,
) {
debug_assert!(plane.len() >= width, "plane too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for (x, &raw) in plane[..width].iter().enumerate() {
let y = if BE {
f32::from_bits(u32::from_be(raw.to_bits()))
} else {
f32::from_bits(u32::from_le(raw.to_bits()))
};
let v = f32_to_u8(y);
let i = x * 4;
rgba_out[i] = v;
rgba_out[i + 1] = v;
rgba_out[i + 2] = v;
rgba_out[i + 3] = 0xFF;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn grayf32_to_rgb_u16_row<const BE: bool>(
plane: &[f32],
rgb_u16_out: &mut [u16],
width: usize,
) {
debug_assert!(plane.len() >= width, "plane too short");
debug_assert!(rgb_u16_out.len() >= width * 3, "rgb_u16_out too short");
for (x, &raw) in plane[..width].iter().enumerate() {
let y = if BE {
f32::from_bits(u32::from_be(raw.to_bits()))
} else {
f32::from_bits(u32::from_le(raw.to_bits()))
};
let v = f32_to_u16(y);
let i = x * 3;
rgb_u16_out[i] = v;
rgb_u16_out[i + 1] = v;
rgb_u16_out[i + 2] = v;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn grayf32_to_rgba_u16_row<const BE: bool>(
plane: &[f32],
rgba_u16_out: &mut [u16],
width: usize,
) {
debug_assert!(plane.len() >= width, "plane too short");
debug_assert!(rgba_u16_out.len() >= width * 4, "rgba_u16_out too short");
for (x, &raw) in plane[..width].iter().enumerate() {
let y = if BE {
f32::from_bits(u32::from_be(raw.to_bits()))
} else {
f32::from_bits(u32::from_le(raw.to_bits()))
};
let v = f32_to_u16(y);
let i = x * 4;
rgba_u16_out[i] = v;
rgba_u16_out[i + 1] = v;
rgba_u16_out[i + 2] = v;
rgba_u16_out[i + 3] = 0xFFFF;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn grayf32_to_rgb_f32_row<const BE: bool>(
plane: &[f32],
rgb_f32_out: &mut [f32],
width: usize,
) {
debug_assert!(plane.len() >= width, "plane too short");
debug_assert!(rgb_f32_out.len() >= width * 3, "rgb_f32_out too short");
for (x, &raw) in plane[..width].iter().enumerate() {
let y = if BE {
f32::from_bits(u32::from_be(raw.to_bits()))
} else {
f32::from_bits(u32::from_le(raw.to_bits()))
};
let i = x * 3;
rgb_f32_out[i] = y;
rgb_f32_out[i + 1] = y;
rgb_f32_out[i + 2] = y;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn grayf32_to_luma_row<const BE: bool>(
plane: &[f32],
luma_out: &mut [u8],
width: usize,
) {
debug_assert!(plane.len() >= width, "plane too short");
debug_assert!(luma_out.len() >= width, "luma_out too short");
for (out, &raw) in luma_out[..width].iter_mut().zip(plane[..width].iter()) {
let y = if BE {
f32::from_bits(u32::from_be(raw.to_bits()))
} else {
f32::from_bits(u32::from_le(raw.to_bits()))
};
*out = f32_to_u8(y);
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn grayf32_to_luma_u16_row<const BE: bool>(
plane: &[f32],
luma_u16_out: &mut [u16],
width: usize,
) {
debug_assert!(plane.len() >= width, "plane too short");
debug_assert!(luma_u16_out.len() >= width, "luma_u16_out too short");
for (out, &raw) in luma_u16_out[..width].iter_mut().zip(plane[..width].iter()) {
let y = if BE {
f32::from_bits(u32::from_be(raw.to_bits()))
} else {
f32::from_bits(u32::from_le(raw.to_bits()))
};
*out = f32_to_u16(y);
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn grayf32_to_luma_f32_row<const BE: bool>(
plane: &[f32],
luma_f32_out: &mut [f32],
width: usize,
) {
debug_assert!(plane.len() >= width, "plane too short");
debug_assert!(luma_f32_out.len() >= width, "luma_f32_out too short");
const HOST_NATIVE_BE: bool = cfg!(target_endian = "big");
if BE == HOST_NATIVE_BE {
luma_f32_out[..width].copy_from_slice(&plane[..width]);
return;
}
for (out, &raw) in luma_f32_out[..width].iter_mut().zip(plane[..width].iter()) {
*out = if BE {
f32::from_bits(u32::from_be(raw.to_bits()))
} else {
f32::from_bits(u32::from_le(raw.to_bits()))
};
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn grayf32_to_hsv_row<const BE: bool>(
plane: &[f32],
h_out: &mut [u8],
s_out: &mut [u8],
v_out: &mut [u8],
width: usize,
) {
debug_assert!(plane.len() >= width, "plane too short");
debug_assert!(h_out.len() >= width, "h_out too short");
debug_assert!(s_out.len() >= width, "s_out too short");
debug_assert!(v_out.len() >= width, "v_out too short");
for (x, &raw) in plane[..width].iter().enumerate() {
let y = if BE {
f32::from_bits(u32::from_be(raw.to_bits()))
} else {
f32::from_bits(u32::from_le(raw.to_bits()))
};
h_out[x] = 0;
s_out[x] = 0;
v_out[x] = f32_to_u8(y);
}
}
#[cfg(all(test, feature = "std"))]
mod tests;