Skip to content

Commit

Permalink
Working tame-twindragon decomposition
Browse files Browse the repository at this point in the history
  • Loading branch information
pagmerek committed Nov 12, 2023
1 parent a997614 commit 8f8a8da
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 43 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk

/img

# images
*.bmp
*.png
*.jpg

# frave data format
*.frv
Expand Down
Binary file added img/decomposition.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn encode(path: PathBuf, var: Variant, output: String) {

let mut enc = FractalImage::new_from_img(img.into_luma8(), var);
enc.find_coef();
// enc.quantizate(&get_quantization_matrix());
enc.quantizate(&get_quantization_matrix());
let (coef, contexts) = enc.ans_encode();
let compressed = Frv::new(enc.height, enc.width, contexts, var, coef);
let mut f = File::create(output).unwrap_or_else(|e| panic!("Failed to encode frv image: {e}"));
Expand All @@ -27,7 +27,7 @@ pub fn decode(path: PathBuf, output: String) {
let frv_img: Frv = bincode::deserialize_from(img).unwrap();
let mut dec = FractalImage::new_from_frv(&frv_img);
dec.ans_decode(frv_img.data, frv_img.ans_contexts);
// dec.unquantizate(&get_quantization_matrix());
dec.unquantizate(&get_quantization_matrix());
dec.find_val();
dec.image.save(output).unwrap_or_else(|e| {
panic!("Failed to decode frv image: {e}");
Expand Down
29 changes: 20 additions & 9 deletions src/compression/decoder.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use std::collections::HashMap;

use itertools::Itertools;
use rans::b64_decoder::B64RansDecoderMulti;
use rans::RansDecoderMulti;

use crate::compression::ans::{self, AnsContext};
use crate::fractal::image::FractalImage;
use crate::utils::bitwise;
use crate::utils::coordinate::Coord;
use crate::utils::{self, Coord};

use super::encoder::Encoder;

pub trait Decoder {
/// Entropy decoding step of decoder procedure.
Expand Down Expand Up @@ -35,7 +37,7 @@ impl Decoder for FractalImage {
.iter()
.enumerate()
.map(|(i, coefficient)| {
let layer = bitwise::get_prev_power_two(i + 1).trailing_zeros();
let layer = utils::get_prev_power_two(i + 1).trailing_zeros();
(*coefficient).map(|s| s * quantization_matrix[layer as usize])
})
.collect::<Vec<Option<i32>>>();
Expand Down Expand Up @@ -66,16 +68,19 @@ impl Decoder for FractalImage {
}

fn ans_decode(&mut self, compressed_coef: Vec<u8>, ans_contexts: Vec<AnsContext>) {
let mut coef = vec![];
let depth = self.depth;
self.find_coef();
let length = self.coef.iter().filter(|x| x.is_some()).count();
let mut coef = self.coef.clone();
let depth = utils::get_prev_power_two(length).trailing_zeros() + 1;
let scale_bits = u32::try_from(depth - 1).unwrap();
let mut decoder: B64RansDecoderMulti<3> = B64RansDecoderMulti::new(compressed_coef);
let ctxs = ans_contexts;
let layers = vec![
0..(1 << (depth - 2)),
(1 << (depth - 2))..(1 << (depth - 1)),
(1 << (depth - 1))..(1 << depth),
0..1 << (depth - 2),
1 << (depth - 2)..1 << (depth - 1),
1 << (depth - 1)..length,
];
let mut last = 0;
for (i, layer) in layers.iter().enumerate() {
let mut cum_freqs = ans::cum_sum(&ctxs[2 - i].freq);
let cum_freq_to_symbols = ans::freqs_to_dec_symbols(&cum_freqs, &ctxs[2 - i].freq);
Expand All @@ -93,9 +98,15 @@ impl Decoder for FractalImage {
let symbol = symbol_map[&cum_freq_decoded];
decoder.advance_step_at(i, &cum_freq_to_symbols[&cum_freq_decoded], scale_bits);
decoder.renorm_at(i);
coef.push(Some(symbol));
last = insert_after_none_starting_from(symbol, last, &mut coef);
}
}
self.coef = coef;
}
}

fn insert_after_none_starting_from(element: i32, i: usize, vec: &mut Vec<Option<i32>>) -> usize {
let ind = (i..vec.len()).find(|j| vec[*j].is_some()).unwrap();
vec[ind] = Some(element);
ind + 1
}
26 changes: 13 additions & 13 deletions src/compression/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ use rans::RansEncoderMulti;

use crate::compression::ans::{self, AnsContext};
use crate::fractal::image::FractalImage;
use crate::utils::bitwise;
use crate::utils::coordinate::Coord;
use crate::utils::{self, Coord};

fn try_apply<T: Copy>(first: Option<T>, second: Option<T>, operation: fn(T, T) -> T) -> Option<T> {
match (first, second) {
Expand Down Expand Up @@ -55,7 +54,7 @@ impl Encoder for FractalImage {
);
self.coef[1] = try_apply(rt, lt, |r, l| (r - l) / 2);
self.coef[0] = try_apply(rt, lt, |r, l| (r + l) / 2);
dbg!(self.coef.iter().filter(|x| x.is_some()).count());
// dbg!(self.coef.iter().filter(|x| x.is_some()).count());
}

fn fn_cf(&mut self, cn: Coord, ps: usize, dp: usize) -> Option<i32> {
Expand All @@ -78,40 +77,41 @@ impl Encoder for FractalImage {
.iter()
.enumerate()
.map(|(i, coefficient)| {
let layer = bitwise::get_prev_power_two(i + 1).trailing_zeros();
let layer = utils::get_prev_power_two(i + 1).trailing_zeros();
(*coefficient).map(|s| s / quantization_matrix[layer as usize])
})
.collect::<Vec<Option<i32>>>();
}

fn ans_encode(&self) -> (Vec<u8>, Vec<AnsContext>) {
dbg!(&self.coef);
let layer1 = &self.coef[1 << (self.depth - 1)..];
let layer2 = &self.coef[1 << (self.depth - 2)..1 << (self.depth - 1)];
let layer3 = &self.coef[..1 << (self.depth - 2)];
let valid_coef = &self.coef.clone().into_iter().flatten().collect::<Vec<i32>>();
let true_depth = utils::get_prev_power_two(valid_coef.len()).trailing_zeros() + 1;
let layer1 = &valid_coef[1 << (true_depth - 1)..];
let layer2 = &valid_coef[1 << (true_depth - 2)..1 << (true_depth - 1)];
let layer3 = &valid_coef[..1 << (true_depth - 2)];

let mut encoder: B64RansEncoderMulti<3> = B64RansEncoderMulti::new(1 << self.depth);
let mut encoder: B64RansEncoderMulti<3> = B64RansEncoderMulti::new(valid_coef.len());
let mut contexts: Vec<ans::AnsContext> = vec![];

for (i, layer) in [layer1, layer2, layer3].into_iter().enumerate() {
let some_layer = layer.iter().flatten();
let counter = some_layer.clone().counts();
let counter = layer.clone().into_iter().counts();
let freq = counter
.values()
.map(|e| u32::try_from(*e).unwrap())
.collect::<Vec<u32>>();
let symbols = counter.keys().map(|e| **e).collect::<Vec<i32>>();
let cdf = ans::cum_sum(&freq);

let symbol_map = ans::freqs_to_enc_symbols(&cdf, &freq, self.depth);
let symbol_map = ans::freqs_to_enc_symbols(&cdf, &freq, true_depth as usize);

let cdf_map = counter
.clone()
.into_keys()
.zip(cdf.clone())
.collect::<HashMap<&i32, u32>>();

some_layer
layer
.iter()
.rev()
.for_each(|s| encoder.put_at(i, &symbol_map[&cdf_map[s]]));

Expand Down
8 changes: 4 additions & 4 deletions src/fractal/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};

use crate::compression::ans::AnsContext;
use crate::fractal::variants::Variant;
use crate::utils::coordinate::Coord;
use crate::utils::Coord;

#[derive(Serialize, Deserialize)]
pub struct Frv {
Expand Down Expand Up @@ -99,7 +99,7 @@ impl FractalImage {
.find(|&(_i, rw, rh)| img_w as i32 <= rw && img_h as i32 <= rh)
.unwrap()
.0
- 1
-1
}

fn find_center(depth: usize, variant: [Coord; 30]) -> Coord {
Expand All @@ -124,7 +124,7 @@ impl FractalImage {

#[inline]
pub fn set_pixel(&mut self, x: i32, y: i32, v: i32) {
let (x, y) = (u32::try_from(x).unwrap(), u32::try_from(y).unwrap());
let (x, y) = (x as u32, y as u32);
let gray = v.clamp(0, 255) as u8;
if x < self.width && y < self.height {
self.image.put_pixel(x, y, image::Luma([gray]));
Expand All @@ -140,6 +140,6 @@ pub fn get_quantization_matrix_soft() -> Vec<i32> {
#[must_use]
pub fn get_quantization_matrix() -> Vec<i32> {
vec![
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 9, 2,
1, 1, 1,1,1,1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 10, 10, 10, 10, 16, 9, 2,
]
}
2 changes: 1 addition & 1 deletion src/fractal/variants.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::utils::coordinate::Coord;
use crate::utils::Coord;
use clap::ValueEnum;
use serde::{Deserialize, Serialize};

Expand Down
28 changes: 28 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use std::ops;

#[derive(Clone, Copy, Debug)]
pub struct Coord {
pub x: i32,
pub y: i32,
}

impl ops::Add<Self> for Coord {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
}

pub const fn get_prev_power_two(x: usize) -> usize {
let mut num = x;
num |= num >> 1;
num |= num >> 2;
num |= num >> 4;
num |= num >> 8;
num |= num >> 16;

num ^ (num >> 1)
}
10 changes: 0 additions & 10 deletions src/utils/bitwise.rs

This file was deleted.

2 changes: 0 additions & 2 deletions src/utils/mod.rs

This file was deleted.

File renamed without changes.

0 comments on commit 8f8a8da

Please sign in to comment.