#[cfg_attr(not(tarpaulin), inline(always))]
fn mono1bit_to_luma_row_generic<const INVERT: bool>(data: &[u8], out: &mut [u8], width: usize) {
debug_assert!(data.len() >= width.div_ceil(8), "data too short");
debug_assert!(out.len() >= width, "out too short");
let mut out_idx = 0;
for byte_val in data.iter().take(width.div_ceil(8)) {
for bit_pos in (0..8).rev() {
if out_idx >= width {
break;
}
let bit = (*byte_val >> bit_pos) & 1;
let luma = if INVERT { (1 - bit) * 255 } else { bit * 255 };
out[out_idx] = luma;
out_idx += 1;
}
}
}
#[inline(always)]
fn pixel_y<const INVERT: bool>(byte: u8, bit: usize) -> u8 {
let raw = (byte >> (7 - bit)) & 1;
if INVERT { (1 - raw) * 255 } else { raw * 255 }
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn mono1bit_to_rgb_generic<const INVERT: bool>(data: &[u8], out: &mut [u8], width: usize) {
debug_assert!(data.len() >= width.div_ceil(8));
debug_assert!(out.len() >= width * 3);
let full_bytes = width / 8;
for (byte_idx, &byte) in data[..full_bytes].iter().enumerate() {
for bit in 0..8usize {
let y = pixel_y::<INVERT>(byte, bit);
let i = (byte_idx * 8 + bit) * 3;
out[i] = y;
out[i + 1] = y;
out[i + 2] = y;
}
}
let tail = width % 8;
if tail > 0 {
let byte = data[full_bytes];
for bit in 0..tail {
let y = pixel_y::<INVERT>(byte, bit);
let i = (full_bytes * 8 + bit) * 3;
out[i] = y;
out[i + 1] = y;
out[i + 2] = y;
}
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn mono1bit_to_rgba_generic<const INVERT: bool>(data: &[u8], out: &mut [u8], width: usize) {
debug_assert!(data.len() >= width.div_ceil(8));
debug_assert!(out.len() >= width * 4);
let full_bytes = width / 8;
for (byte_idx, &byte) in data[..full_bytes].iter().enumerate() {
for bit in 0..8usize {
let y = pixel_y::<INVERT>(byte, bit);
let i = (byte_idx * 8 + bit) * 4;
out[i] = y;
out[i + 1] = y;
out[i + 2] = y;
out[i + 3] = 0xFF;
}
}
let tail = width % 8;
if tail > 0 {
let byte = data[full_bytes];
for bit in 0..tail {
let y = pixel_y::<INVERT>(byte, bit);
let i = (full_bytes * 8 + bit) * 4;
out[i] = y;
out[i + 1] = y;
out[i + 2] = y;
out[i + 3] = 0xFF;
}
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn mono1bit_to_rgb_u16_generic<const INVERT: bool>(data: &[u8], out: &mut [u16], width: usize) {
debug_assert!(data.len() >= width.div_ceil(8));
debug_assert!(out.len() >= width * 3);
let full_bytes = width / 8;
for (byte_idx, &byte) in data[..full_bytes].iter().enumerate() {
for bit in 0..8usize {
let y16 = pixel_y::<INVERT>(byte, bit) as u16;
let i = (byte_idx * 8 + bit) * 3;
out[i] = y16;
out[i + 1] = y16;
out[i + 2] = y16;
}
}
let tail = width % 8;
if tail > 0 {
let byte = data[full_bytes];
for bit in 0..tail {
let y16 = pixel_y::<INVERT>(byte, bit) as u16;
let i = (full_bytes * 8 + bit) * 3;
out[i] = y16;
out[i + 1] = y16;
out[i + 2] = y16;
}
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn mono1bit_to_rgba_u16_generic<const INVERT: bool>(data: &[u8], out: &mut [u16], width: usize) {
debug_assert!(data.len() >= width.div_ceil(8));
debug_assert!(out.len() >= width * 4);
let full_bytes = width / 8;
for (byte_idx, &byte) in data[..full_bytes].iter().enumerate() {
for bit in 0..8usize {
let y16 = pixel_y::<INVERT>(byte, bit) as u16;
let i = (byte_idx * 8 + bit) * 4;
out[i] = y16;
out[i + 1] = y16;
out[i + 2] = y16;
out[i + 3] = 0x00FF;
}
}
let tail = width % 8;
if tail > 0 {
let byte = data[full_bytes];
for bit in 0..tail {
let y16 = pixel_y::<INVERT>(byte, bit) as u16;
let i = (full_bytes * 8 + bit) * 4;
out[i] = y16;
out[i + 1] = y16;
out[i + 2] = y16;
out[i + 3] = 0x00FF;
}
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn mono1bit_to_luma_u16_generic<const INVERT: bool>(data: &[u8], out: &mut [u16], width: usize) {
debug_assert!(data.len() >= width.div_ceil(8));
debug_assert!(out.len() >= width);
let full_bytes = width / 8;
for (byte_idx, &byte) in data[..full_bytes].iter().enumerate() {
for bit in 0..8usize {
out[byte_idx * 8 + bit] = pixel_y::<INVERT>(byte, bit) as u16;
}
}
let tail = width % 8;
if tail > 0 {
let byte = data[full_bytes];
for bit in 0..tail {
out[full_bytes * 8 + bit] = pixel_y::<INVERT>(byte, bit) as u16;
}
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn monoblack_to_rgb_row(data: &[u8], out: &mut [u8], width: usize) {
mono1bit_to_rgb_generic::<false>(data, out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn monoblack_to_rgba_row(data: &[u8], out: &mut [u8], width: usize) {
mono1bit_to_rgba_generic::<false>(data, out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn monoblack_to_rgb_u16_row(data: &[u8], out: &mut [u16], width: usize) {
mono1bit_to_rgb_u16_generic::<false>(data, out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn monoblack_to_rgba_u16_row(data: &[u8], out: &mut [u16], width: usize) {
mono1bit_to_rgba_u16_generic::<false>(data, out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn monoblack_to_luma_row(data: &[u8], out: &mut [u8], width: usize) {
mono1bit_to_luma_row_generic::<false>(data, out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn monoblack_to_luma_u16_row(data: &[u8], out: &mut [u16], width: usize) {
mono1bit_to_luma_u16_generic::<false>(data, out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn monoblack_to_hsv_row(
data: &[u8],
h: &mut [u8],
s: &mut [u8],
v: &mut [u8],
width: usize,
) {
mono1bit_to_luma_row_generic::<false>(data, v, width);
for i in 0..width {
h[i] = 0;
s[i] = 0;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn monowhite_to_rgb_row(data: &[u8], out: &mut [u8], width: usize) {
mono1bit_to_rgb_generic::<true>(data, out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn monowhite_to_rgba_row(data: &[u8], out: &mut [u8], width: usize) {
mono1bit_to_rgba_generic::<true>(data, out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn monowhite_to_rgb_u16_row(data: &[u8], out: &mut [u16], width: usize) {
mono1bit_to_rgb_u16_generic::<true>(data, out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn monowhite_to_rgba_u16_row(data: &[u8], out: &mut [u16], width: usize) {
mono1bit_to_rgba_u16_generic::<true>(data, out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn monowhite_to_luma_row(data: &[u8], out: &mut [u8], width: usize) {
mono1bit_to_luma_row_generic::<true>(data, out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn monowhite_to_luma_u16_row(data: &[u8], out: &mut [u16], width: usize) {
mono1bit_to_luma_u16_generic::<true>(data, out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn monowhite_to_hsv_row(
data: &[u8],
h: &mut [u8],
s: &mut [u8],
v: &mut [u8],
width: usize,
) {
mono1bit_to_luma_row_generic::<true>(data, v, width);
for i in 0..width {
h[i] = 0;
s[i] = 0;
}
}