finished decoder and encoder

master
elfeiin 2024-02-14 23:50:05 -08:00
parent 7f9faf0e80
commit 9263929991
Signed by: elfein
GPG Key ID: A53FDD4FD091A276
7 changed files with 253 additions and 122 deletions

16
Cargo.lock generated
View File

@ -14,11 +14,18 @@ dependencies = [
"wyz",
]
[[package]]
name = "either"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
[[package]]
name = "exf"
version = "0.1.0"
dependencies = [
"bitvec",
"itertools",
]
[[package]]
@ -27,6 +34,15 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]]
name = "itertools"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
dependencies = [
"either",
]
[[package]]
name = "radium"
version = "0.7.0"

View File

@ -7,3 +7,4 @@ edition = "2021"
[dependencies]
bitvec = "1.0.1"
itertools = "0.12.1"

View File

@ -4,30 +4,30 @@ use exf::{read_quad_tree, ImageData};
fn main() {
#[rustfmt::skip]
let data = bitvec::bitvec![
1,1,
1,1,
0,0,
0,0,
0,0,
0,0,
1,1,
1,1,
1,0,
0,1,
0,0,
0,0,
1,1,
1,1,
1,0,
0,1,
0,0,
0,0,
1,1,
1,1,
1,0,
0,1,
0,0,
0,0,
1,1,
1,1,
1,0,
0,1,
];
let image_data = ImageData::default();
let slice2d = image_data.get_slice2d((0..64, 0..64));
read_quad_tree(&mut data.into_iter(), slice2d);
let slice2d = image_data.get_slice2d((0..16, 0..16));
read_quad_tree(&mut data.into_iter(), slice2d).unwrap();
for n in image_data.data.borrow_mut().into_iter() {
let n = n.reverse_bits();
let n = n.to_be();
println!["{n:064b}"];
}
}

86
src/decoder.rs Normal file
View File

@ -0,0 +1,86 @@
use crate::{slice2d::Slice2D, Element, ImageData};
use bitvec::vec::BitVec;
pub fn read_element_bits(input: &mut dyn Iterator<Item = bool>) -> BitVec {
let mut output = BitVec::new();
loop {
output.extend(input.take(7));
if !input.next().unwrap_or_default() {
break;
}
}
output
}
pub fn read_quad_tree(input: &mut dyn Iterator<Item = bool>, output: Slice2D) -> Result<(), ()> {
let header = input.take(4).collect::<Vec<bool>>();
if header.len() != 4 {
return Err(());
}
let (hlen, vlen) = output.len();
let hmid = hlen / 2;
let vmid = vlen / 2;
let quadrants = [
output.get_slice2d((0..hmid, 0..vmid)),
output.get_slice2d((hmid..hlen, 0..vmid)),
output.get_slice2d((0..hmid, vmid..vlen)),
output.get_slice2d((hmid..hlen, vmid..vlen)),
];
if hlen == 2 || vlen == 2 {
for (quadrant, v) in quadrants.into_iter().zip(header.into_iter()) {
quadrant.set(v, (0, 0));
}
} else {
for (quadrant, homogenous) in quadrants.into_iter().zip(header.into_iter()) {
if homogenous {
if let Some(value) = input.next() {
quadrant.set_all(value);
} else {
return Err(());
}
} else {
read_quad_tree(input, quadrant)?;
}
}
}
Ok(())
}
pub fn parse_element(input: &mut dyn Iterator<Item = bool>) -> Result<Element, ()> {
let element_bits = read_element_bits(input);
let mut input = element_bits.into_iter();
if let Some(is_glyph) = input.next() {
if is_glyph {
if let Some(cs) = input.next() {
let image_data = ImageData::default();
let slice_2d = image_data.get_slice2d((0..64, 0..64));
read_quad_tree(&mut input, slice_2d)?;
Ok(Element::Glyph {
courtesy_space: cs,
image_data: Box::new(image_data),
})
} else {
Err((/* Not enough data! */))
}
} else {
Ok(Element::ControlCode {
data: input
.take(128)
.enumerate()
.fold(0, |a, (i, b)| a | ((b as u128) << i)),
})
}
} else {
Err((/* No data! */))
}
}
pub fn decode(input: &[u8]) -> Result<Vec<Element>, ()> {
let mut output = Vec::new();
let bits = BitVec::<u8>::from_slice(input);
let mut iter = bits.into_iter().peekable();
while iter.peek().is_some() {
output.push(parse_element(&mut iter)?);
}
Ok(output)
}

79
src/encoder.rs Normal file
View File

@ -0,0 +1,79 @@
use crate::{slice2d::Slice2D, Element};
use bitvec::{slice::BitSlice, vec::BitVec};
pub fn write_element_bits(bits: &BitSlice<u8>, output: &mut BitVec<u8>) {
let mut iter = bits.chunks(7).peekable();
while let Some(next_7) = iter.next() {
if iter.peek().is_some() {
output.push(true);
} else {
output.push(false);
}
output.extend_from_bitslice(next_7);
}
}
pub fn write_quad_tree(input: Slice2D, output: &mut BitVec<u8>) {
let (hlen, vlen) = input.len();
let hmid = hlen / 2;
let vmid = vlen / 2;
let quadrants = [
input.get_slice2d((0..hmid, 0..vmid)),
input.get_slice2d((hmid..hlen, 0..vmid)),
input.get_slice2d((0..hmid, vmid..vlen)),
input.get_slice2d((hmid..hlen, vmid..vlen)),
];
let mut buffer = BitVec::<u8>::new();
for quadrant in quadrants {
if let Some(v) = quadrant.get_all() {
output.push(true);
buffer.push(v);
} else {
output.push(false);
write_quad_tree(quadrant, &mut buffer);
}
}
output.extend_from_bitslice(&buffer);
}
pub fn write_element(input: Element, output: &mut BitVec<u8>) {
match input {
Element::ControlCode { data } => {
let mut bits = BitVec::<u8>::new();
bits.push(false);
bits.extend_from_raw_slice(&data.to_le().to_le_bytes());
let mut bitslice = bits.as_bitslice();
for (i, bit) in bits.iter().enumerate() {
if *bit {
bitslice = &bits[i..];
break;
}
}
write_element_bits(bitslice, output);
}
Element::Glyph {
courtesy_space,
image_data,
} => {
let mut bits = BitVec::<u8>::new();
bits.push(true);
bits.push(courtesy_space);
for _ in 0..5 {
bits.push(false);
}
write_quad_tree(image_data.get_slice2d((0..64, 0..64)), &mut bits);
write_element_bits(&bits, output);
}
}
}
pub fn encode(input: Vec<Element>) -> Vec<u8> {
let mut output = Vec::new();
for element in input {
let mut bits = BitVec::<u8>::new();
write_element(element, &mut bits);
bits.set_uninitialized(false);
output.extend_from_slice(&bits.into_vec());
}
output
}

View File

@ -1,35 +1,10 @@
use bitvec::{field::BitField, slice::BitSlice, vec::BitVec};
use std::{cell::RefCell, ops::Range};
pub struct Slice2D<'a> {
buf: &'a ImageData,
h: Range<usize>,
v: Range<usize>,
}
impl<'a> Slice2D<'a> {
pub fn set(&self, value: bool, index: (usize, usize)) {
self.buf
.set(value, (index.0 + self.h.start, index.1 + self.v.start));
}
pub fn set_all(&self, value: bool) {
for v in 0..self.v.clone().len() {
for h in 0..self.h.clone().len() {
self.set(value, (h, v))
}
}
}
pub fn get_slice2d(&'a self, region: (Range<usize>, Range<usize>)) -> Slice2D<'a> {
Slice2D {
buf: self.buf,
h: region.0.start + self.h.start..region.0.end + self.h.start,
v: region.1.start + self.v.start..region.1.end + self.v.start,
}
}
pub fn len(&self) -> (usize, usize) {
(self.h.len(), self.v.len())
}
}
mod decoder;
mod encoder;
mod slice2d;
pub use decoder::*;
pub use encoder::*;
use slice2d::*;
pub struct ImageData {
pub data: RefCell<[u64; 64]>,
@ -44,6 +19,9 @@ impl Default for ImageData {
}
impl<'a> ImageData {
pub fn get(&self, index: (usize, usize)) -> bool {
((self.data.borrow_mut()[index.1] >> index.0) & !1) > 0
}
pub fn set(&self, value: bool, index: (usize, usize)) {
self.data.borrow_mut()[index.1] = if value {
self.data.borrow_mut()[index.1] | (1 << index.0)
@ -60,63 +38,6 @@ impl<'a> ImageData {
}
}
pub fn read_quad_tree(input: &mut dyn Iterator<Item = bool>, output: Slice2D) {
let (i0, i1, i2, i3) = (
input.next().unwrap(),
input.next().unwrap(),
input.next().unwrap(),
input.next().unwrap(),
);
let (hlen, vlen) = output.len();
let hmid = hlen / 2;
let vmid = vlen / 2;
let q0 = output.get_slice2d((0..hmid, 0..vmid));
let q1 = output.get_slice2d((hmid..hlen, 0..vmid));
let q2 = output.get_slice2d((0..hmid, vmid..vlen));
let q3 = output.get_slice2d((hmid..hlen, vmid..vlen));
if hlen == 2 || vlen == 2 {
q0.set(i0, (0, 0));
q1.set(i1, (0, 0));
q2.set(i2, (0, 0));
q3.set(i3, (0, 0));
} else {
if i0 {
read_quad_tree(input, q0);
} else {
q0.set_all(input.next().unwrap());
}
if i1 {
read_quad_tree(input, q1);
} else {
q1.set_all(input.next().unwrap());
}
if i2 {
read_quad_tree(input, q2);
} else {
q2.set_all(input.next().unwrap());
}
if i3 {
read_quad_tree(input, q3);
} else {
q3.set_all(input.next().unwrap());
}
}
}
pub fn read_element_bits(input: &mut &BitSlice) -> BitVec {
let mut output = BitVec::new();
let mut end = 0;
for byte in input.chunks(8) {
output.extend_from_bitslice(&byte[0..7]);
end += 8;
if !byte[7] {
break;
}
}
*input = &input[end..];
output
}
pub enum Element {
ControlCode {
data: u128,
@ -126,24 +47,3 @@ pub enum Element {
image_data: Box<ImageData>,
},
}
pub fn parse_element(input: &mut &BitSlice) -> Element {
let element_bits = read_element_bits(input);
let is_glyph = input[0];
*input = &input[1..];
if is_glyph {
let cs = input[0];
*input = &input[1..];
let image_data = ImageData::default();
let slice_2d = image_data.get_slice2d((0..64, 0..64));
read_quad_tree(&mut element_bits.into_iter(), slice_2d);
Element::Glyph {
courtesy_space: cs,
image_data: Box::new(image_data),
}
} else {
Element::ControlCode {
data: input.load_le(),
}
}
}

49
src/slice2d.rs Normal file
View File

@ -0,0 +1,49 @@
use std::ops::Range;
use crate::ImageData;
pub struct Slice2D<'a> {
pub buf: &'a ImageData,
pub h: Range<usize>,
pub v: Range<usize>,
}
impl<'a> Slice2D<'a> {
// Relative coordinates
pub fn get(&self, index: (usize, usize)) -> bool {
self.buf
.get((index.0 + self.h.start, index.1 + self.v.start))
}
pub fn set(&self, value: bool, index: (usize, usize)) {
self.buf
.set(value, (index.0 + self.h.start, index.1 + self.v.start));
}
pub fn get_all(&self) -> Option<bool> {
let initial = self.get((0, 0));
for v in 0..self.v.clone().len() {
for h in 0..self.h.clone().len() {
if self.get((h, v)) != initial {
return None;
}
}
}
Some(initial)
}
pub fn set_all(&self, value: bool) {
for v in 0..self.v.clone().len() {
for h in 0..self.h.clone().len() {
self.set(value, (h, v))
}
}
}
pub fn get_slice2d(&'a self, region: (Range<usize>, Range<usize>)) -> Slice2D<'a> {
Slice2D {
buf: self.buf,
h: region.0.start + self.h.start..region.0.end + self.h.start,
v: region.1.start + self.v.start..region.1.end + self.v.start,
}
}
pub fn len(&self) -> (usize, usize) {
(self.h.len(), self.v.len())
}
}