pub fn xrgb8888_encode_qoi(bytes: &[u8], width: u32, height: u32, stride: u32) -> Vec { 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(slice: &[T]) -> &[[T; N]] { let len = slice.len() / N; unsafe { std::slice::from_raw_parts(slice.as_ptr() as _, len) } }