refactor: split cargo workspace
This commit is contained in:
parent
5db14936e7
commit
1c21bd1259
695 changed files with 32023 additions and 44964 deletions
91
crates/algorithms/src/qoi.rs
Normal file
91
crates/algorithms/src/qoi.rs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
pub fn xrgb8888_encode_qoi(bytes: &[u8], width: u32, height: u32, stride: u32) -> Vec<u8> {
|
||||
const OP_RGB: u8 = 0b1111_1110;
|
||||
const OP_INDEX: u8 = 0b0000_0000;
|
||||
const OP_DIFF: u8 = 0b0100_0000;
|
||||
const OP_LUMA: u8 = 0b1000_0000;
|
||||
const OP_RUN: u8 = 0b1100_0000;
|
||||
|
||||
let mut res = vec![];
|
||||
let width_bytes_be = width.to_be_bytes();
|
||||
let height_bytes_be = height.to_be_bytes();
|
||||
let header = [
|
||||
b'q',
|
||||
b'o',
|
||||
b'i',
|
||||
b'f',
|
||||
width_bytes_be[0],
|
||||
width_bytes_be[1],
|
||||
width_bytes_be[2],
|
||||
width_bytes_be[3],
|
||||
height_bytes_be[0],
|
||||
height_bytes_be[1],
|
||||
height_bytes_be[2],
|
||||
height_bytes_be[3],
|
||||
3,
|
||||
0,
|
||||
];
|
||||
res.extend_from_slice(&header);
|
||||
let mut prev_pixel = [0, 0, 0, 0xff];
|
||||
let mut array = [[0; 4]; 64];
|
||||
let mut run_length = 0;
|
||||
for line in bytes.chunks_exact(stride as _) {
|
||||
for &pixel in array_chunks::<_, 4>(&line[..(width * 4) as _]) {
|
||||
let pixel = [pixel[2], pixel[1], pixel[0], 0xff];
|
||||
if pixel == prev_pixel {
|
||||
run_length += 1;
|
||||
if run_length == 62 {
|
||||
res.push(OP_RUN | (run_length - 1));
|
||||
run_length = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if run_length > 0 {
|
||||
res.push(OP_RUN | (run_length - 1));
|
||||
run_length = 0;
|
||||
}
|
||||
let prev = prev_pixel;
|
||||
prev_pixel = pixel;
|
||||
let index = {
|
||||
let sum = 0u8
|
||||
.wrapping_add(pixel[0].wrapping_mul(3))
|
||||
.wrapping_add(pixel[1].wrapping_mul(5))
|
||||
.wrapping_add(pixel[2].wrapping_mul(7))
|
||||
.wrapping_add(255u8.wrapping_mul(11));
|
||||
sum & 63
|
||||
};
|
||||
if array[index as usize] == pixel {
|
||||
res.push(OP_INDEX | index);
|
||||
continue;
|
||||
}
|
||||
array[index as usize] = pixel;
|
||||
let dr = pixel[0].wrapping_sub(prev[0]);
|
||||
let dg = pixel[1].wrapping_sub(prev[1]);
|
||||
let db = pixel[2].wrapping_sub(prev[2]);
|
||||
let dr_2 = dr.wrapping_add(2);
|
||||
let dg_2 = dg.wrapping_add(2);
|
||||
let db_2 = db.wrapping_add(2);
|
||||
if dr_2 | dg_2 | db_2 | 3 == 3 {
|
||||
res.push(OP_DIFF | (dr_2 << 4) | (dg_2 << 2) | db_2);
|
||||
continue;
|
||||
}
|
||||
let dr_dg_8 = dr.wrapping_sub(dg).wrapping_add(8);
|
||||
let db_dg_8 = db.wrapping_sub(dg).wrapping_add(8);
|
||||
let dg_32 = dg.wrapping_add(32);
|
||||
if (dg_32 | 63 == 63) && (dr_dg_8 | db_dg_8 | 15 == 15) {
|
||||
res.extend_from_slice(&[OP_LUMA | dg_32, (dr_dg_8 << 4) | db_dg_8]);
|
||||
continue;
|
||||
}
|
||||
res.extend_from_slice(&[OP_RGB, pixel[0], pixel[1], pixel[2]]);
|
||||
}
|
||||
}
|
||||
if run_length > 0 {
|
||||
res.push(OP_RUN | (run_length - 1));
|
||||
}
|
||||
res.extend_from_slice(&[0, 0, 0, 0, 0, 0, 0, 1]);
|
||||
res
|
||||
}
|
||||
|
||||
fn array_chunks<T, const N: usize>(slice: &[T]) -> &[[T; N]] {
|
||||
let len = slice.len() / N;
|
||||
unsafe { std::slice::from_raw_parts(slice.as_ptr() as _, len) }
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue