Skip to content

Commit b0cb4d5

Browse files
author
kmgx
committedNov 3, 2019
HW1 final
1 parent a914b5e commit b0cb4d5

16 files changed

+1155
-26
lines changed
 

‎Arithmetic-Coding/Cargo.lock

+456
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Arithmetic-Coding/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ edition = "2018"
77
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
88

99
[dependencies]
10+
structopt = "0.3.3"
11+
rug = "1.6.0"

‎Arithmetic-Coding/gates.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
BILL GATES

‎Arithmetic-Coding/lorem-ipsum.txt

+99
Large diffs are not rendered by default.

‎Arithmetic-Coding/output.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
BILL GATES

‎Arithmetic-Coding/src/main.rs

+131-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,133 @@
1+
use structopt::StructOpt;
2+
use std::fs;
3+
use std::collections::HashMap;
4+
use rug::{Float, ops::AssignRound, float::Round};
5+
use std::mem;
6+
7+
#[derive(StructOpt, Debug)]
8+
#[structopt(name = "basic")]
9+
struct Opt {
10+
#[structopt(name = "FILE")]
11+
file: String
12+
}
13+
14+
15+
fn find_frequencies(data : &String) -> HashMap<char, u32> {
16+
let mut frequencies : HashMap<char, u32> = HashMap::new();
17+
18+
for c in data.chars() {
19+
// Read previous character count
20+
let mut cur_count : u32 = 0;
21+
if let Some(&count) = frequencies.get(&c) { cur_count = count; }
22+
23+
// Increase it
24+
let entry = frequencies.entry(c).or_insert(cur_count);
25+
*entry = *entry + 1;
26+
}
27+
28+
return frequencies;
29+
}
30+
31+
fn compression_ratio(before: &String, after: &Float) -> f64 {
32+
let before_size = mem::size_of_val(&before[..]);
33+
let after_size = after.prec() + 32;
34+
println!("before : {:?}, after : {:?}", before_size, after_size);
35+
return after_size as f64 / before_size as f64;
36+
37+
}
38+
39+
fn find_bounds(freqs: &HashMap<char, u32>, filesize: u32, step_precision: u32) -> HashMap<char, (Float, Float)> {
40+
let mut bounds : HashMap<char, (Float, Float)> = HashMap::new();
41+
42+
let mut prevhigh = Float::with_val(step_precision, 0.0);
43+
for (&c, &count) in freqs {
44+
let low = prevhigh;
45+
let high = Float::with_val(step_precision, low.clone() + (count as f64 / filesize as f64));
46+
prevhigh = Float::with_val(step_precision, high.clone());
47+
48+
bounds.insert(c, (low, high));
49+
}
50+
51+
return bounds;
52+
}
53+
54+
fn arithmetic_encode(file: &String, bounds: &HashMap<char, (Float, Float)>, step_precision: u32) -> Float {
55+
56+
// Start with 1-bit precision
57+
let mut high : Float = Float::with_val(32, 1);
58+
let mut low : Float = Float::with_val(32, 0);
59+
60+
for c in file.chars() {
61+
62+
// Increase the precision of the floats
63+
high.set_prec(high.prec() + step_precision);
64+
low.set_prec(low.prec() + step_precision);
65+
66+
//println!("{:?} : {:?}, {:?}, {:?}, {:?}, ", c, low.prec(), high.prec(), high, low);
67+
68+
let range = high.clone() - low.clone();
69+
70+
//println!("{:?} : {:?}, {:?}, {:?}, {:?}, {:?}, ", c, low.prec(), high.prec(), range, high, low);
71+
72+
high.assign_round(low.clone() + (range.clone() * bounds.get(&c).unwrap().1.clone()), Round::Down);
73+
low.assign_round(low.clone() + (range.clone() * bounds.get(&c).unwrap().0.clone()), Round::Up);
74+
//println!("{:?} : {:?}, {:?}, {:?}, {:?}, {:?}, ", c, low.prec(), high.prec(), range, high, low);
75+
}
76+
77+
return (high + low)/2;
78+
}
79+
80+
fn arithmetic_decode(encoded : &Float, bounds: &HashMap<char, (Float, Float)>, filesize : u32, step_precision: u32) -> String {
81+
let mut result : String = String::new();
82+
let mut data = encoded.clone();
83+
84+
// Initial precision is 32, so get back to that
85+
while data.prec() > 32 {
86+
for(c, bounds) in bounds {
87+
if bounds.1 > data && bounds.0 < data {
88+
println!("{:?} : {:?} at prec {:?}, bounds are {:?} - {:?}", c, data, data.prec(), bounds.0.clone(), bounds.1.clone());
89+
result.push(*c);
90+
data.assign_round((data.clone() - bounds.0.clone()) / (bounds.1.clone() - bounds.0.clone()), Round::Up);
91+
data.set_prec(data.prec() - step_precision);
92+
break;
93+
}
94+
}
95+
}
96+
97+
return result;
98+
}
99+
1100
fn main() {
2-
println!("Hello, world!");
101+
// Parse arguments
102+
let opt = Opt::from_args();
103+
104+
println!("Reading file");
105+
let contents = fs::read_to_string(opt.file).unwrap();
106+
let filesize = contents.len() as u32;
107+
108+
// https://stackoverflow.com/questions/7150035/ and add a small pad :)
109+
let step_precision = (filesize as f64).log2().ceil() as u32;
110+
println!("Step precision : {:?}", step_precision);
111+
112+
// Find frequency
113+
let frequencies = find_frequencies(&contents);
114+
let bounds = find_bounds(&frequencies, filesize, step_precision);
115+
println!("{:?}\n{:?}", frequencies.clone(), bounds.clone());
116+
117+
// Encode file
118+
let encoded = arithmetic_encode(&contents, &bounds, step_precision);
119+
println!("encoder result : {:?}", encoded);
120+
121+
// Compute compression ratio
122+
let ratio = compression_ratio(&contents, &encoded);
123+
println!("Compression ratio : {:?}", ratio);
124+
125+
// Decode file
126+
let decoded = arithmetic_decode(&encoded, &bounds, filesize, step_precision);
127+
println!("decoder result : {:?}", decoded);
128+
129+
println!("Saving result");
130+
fs::write("output.txt", &decoded[..]).unwrap();
131+
132+
3133
}

‎Ordered-Dithering/Bayer-5.png

6.2 KB
Loading

‎Ordered-Dithering/mmp.jpg

109 KB
Loading

‎Ordered-Dithering/output.txt

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
Compiling Ordered-Dithering v0.1.0 (/media/chris/Data/Github/MultimediaSignalProcessingClass/Ordered-Dithering)
2+
error[E0425]: cannot find value `index` in this scope
3+
--> src/main.rs:46:26
4+
|
5+
46 | let img_x = index % img_width;
6+
| ^^^^^ not found in this scope
7+
8+
error[E0425]: cannot find value `index` in this scope
9+
--> src/main.rs:47:27
10+
|
11+
47 | let img_y = ((index as f64 - img_x as f64) / img_height as f64).floor();
12+
| ^^^^^ not found in this scope
13+
14+
error[E0425]: cannot find value `index` in this scope
15+
--> src/main.rs:53:61
16+
|
17+
53 | println!("{:?}, {:?}, {:?}, {:?}, {:?}, {:?},", index, img_y, img_x, dither_y, dither_x, dither_index);
18+
| ^^^^^ not found in this scope
19+
20+
error[E0599]: no method named `floor` found for type `u32` in the current scope
21+
--> src/main.rs:62:57
22+
|
23+
62 | let buffer = image::ImageBuffer::from_vec(img_width.floor() as u32, img_height.floor() as u32, result).unwrap();
24+
| ^^^^^
25+
26+
error[E0599]: no method named `floor` found for type `u32` in the current scope
27+
--> src/main.rs:62:84
28+
|
29+
62 | let buffer = image::ImageBuffer::from_vec(img_width.floor() as u32, img_height.floor() as u32, result).unwrap();
30+
| ^^^^^
31+
32+
warning: unused import: `rayon::prelude`
33+
--> src/main.rs:3:5
34+
|
35+
3 | use rayon::prelude::*;
36+
| ^^^^^^^^^^^^^^
37+
|
38+
= note: #[warn(unused_imports)] on by default
39+
40+
error: aborting due to 5 previous errors
41+
42+
Some errors have detailed explanations: E0425, E0599.
43+
For more information about an error, try `rustc --explain E0425`.
44+
error: Could not compile `Ordered-Dithering`.
45+
46+
To learn more, run the command again with --verbose.

‎Ordered-Dithering/output_bayer.png

54 Bytes
Loading
9 Bytes
Loading

‎Ordered-Dithering/src/input.png

-58.1 KB
Binary file not shown.

‎Ordered-Dithering/src/main.rs

+14-15
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,30 @@ fn apply_dithering(image: image::DynamicImage, dither_array : [f32; 64]) -> imag
3636

3737
let mut pixels = image.raw_pixels();
3838
let size = image.dimensions();
39-
let img_width = size.0;
40-
let img_height = size.1;
39+
let img_width = size.0 as usize;
40+
let img_height = size.1 as usize;
4141
let dither_width = 8;
4242
let dither_height = 8;
4343

44-
let result = pixels.par_iter_mut().enumerate().map(|(index, pixel)| {
45-
let img_x = (index as u32) % img_width;
46-
let img_y = ((index as u32) - img_x) / img_height;
44+
// println!("{:?}", pixels);
45+
let result = pixels.into_par_iter().enumerate().map(|(index, pixel)| {
46+
let img_x : usize = index % img_width;
47+
let img_y : usize = ((index as f64 - img_x as f64) / img_width as f64).floor() as usize;
4748

4849
let dither_x = img_x % dither_width;
4950
let dither_y = img_y % dither_height;
50-
let dither_index = dither_x + (dither_y * dither_width);
51-
let dither_val = dither_array[dither_index as usize];
5251

53-
let downscaled_pix : f32 = (*pixel as f32) / 255.0;
54-
let result_pixel = match downscaled_pix {
55-
downscaled_pix if downscaled_pix < dither_val => 0,
56-
downscaled_pix if downscaled_pix > dither_val => 255,
57-
_ => 255 // ARBITRARY CHOICE !
58-
};
52+
let dither_index = dither_x + (dither_y * dither_width);
53+
//println!("{:?}, {:?}, {:?}, {:?}, {:?}, {:?},", index, img_y, img_x, dither_y, dither_x, dither_index);
54+
let dither_val = dither_array[dither_index];
55+
5956

60-
return result_pixel;
57+
if (pixel as f32) / 255.0 < dither_val {
58+
return 0;
59+
} else { return 255; }
6160
}).collect();
6261

63-
let buffer = image::ImageBuffer::from_vec(img_width, img_height, result).unwrap();
62+
let buffer = image::ImageBuffer::from_vec(img_width as u32, img_height as u32, result).unwrap();
6463
return image::DynamicImage::ImageLuma8(buffer);
6564
}
6665

21.3 KB
Binary file not shown.

0 commit comments

Comments
 (0)
Please sign in to comment.