finished decoder and encoder
parent
7f9faf0e80
commit
9263929991
|
@ -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"
|
||||
|
|
|
@ -7,3 +7,4 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
bitvec = "1.0.1"
|
||||
itertools = "0.12.1"
|
||||
|
|
|
@ -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}"];
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
118
src/lib.rs
118
src/lib.rs
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue