use image::GenericImageView;
extern crate image;
pub enum Coloring {
RedGreen,
RedBlue,
RedCyan,
Anachrome,
Mirachrome,
Trioscopic,
Colorcode3D,
MagentaCyan,
}
const PURERED: [f32 ; 3] = [255./255., 0./255., 0./255.];
const PUREGREEN: [f32 ; 3] = [0./255., 255./255., 0./255.];
const PUREBLUE: [f32 ; 3] = [0./255., 0./255., 255./255.];
const PURECYAN: [f32 ; 3] = [0./255., 255./255., 255./255.];
const DARKRED: [f32 ; 3] = [204./255., 0./255., 0./255.];
const CYAN: [f32 ; 3] = [153./255., 204./255., 255./255.];
const PUREMAGENTA: [f32 ; 3] = [255./255., 0./255., 255./255.];
const AMBER: [f32 ; 3] = [255./255., 191./255., 0./255.];
const DARKBLUE: [f32 ; 3] = [0./255., 0./255., 153./255.];
pub fn create(input_file: &str, output_file: &str, offset_x: isize, offset_y: isize, coloring: Coloring) -> () {
let offset_x = offset_x /2;
let offset_y = offset_y /2;
let direction: &str = {
if offset_x>=0 {
if offset_y>=0 { "bottomright" }
else { "topright" }
}
else {
if offset_y>=0 { "bottomleft" }
else { "topleft" }
}
};
let direction = direction.to_owned();
let (color_left, color_right): (_, _) = match coloring {
Coloring::RedGreen => (PURERED, PUREGREEN),
Coloring::RedBlue => (PURERED, PUREBLUE),
Coloring::RedCyan => (PURERED, PURECYAN),
Coloring::Anachrome => (DARKRED, CYAN),
Coloring::Mirachrome => (DARKRED, CYAN),
Coloring::Trioscopic => (PUREGREEN, PUREMAGENTA),
Coloring::Colorcode3D => (AMBER, DARKBLUE),
Coloring::MagentaCyan => (PUREMAGENTA, PURECYAN),
};
let img = image::open(input_file).unwrap();
let (in_x, in_y) = img.dimensions();
let (in_x, in_y) = (in_x as isize, in_y as isize);
let out_x = in_x - offset_x.abs();
let out_y = in_y - offset_y.abs();
let in_buf = img.to_rgb8().into_raw();
let mut out_buf = vec![0u8 ; (out_x * out_y * 3) as usize];
println!("Direction {}, In {}, Out {}", direction, in_x*in_y * 3, out_x * out_y * 3);
let mut anaglyph = Anaglyph {
in_buf,
offset_x: offset_x.abs() as usize,
in_x: in_x.abs() as usize,
out_x: out_x.abs() as usize,
offset_y: offset_y.abs() as usize,
color_left,
color_right,
direction,
};
anaglyph.fill(&mut out_buf);
image::save_buffer(&output_file, &out_buf, out_x as u32, out_y as u32, image::ColorType::Rgb8).unwrap();
}
struct Anaglyph {
in_buf: Vec<u8>,
offset_x: usize,
in_x: usize,
out_x: usize,
offset_y: usize,
color_left: [f32 ; 3],
color_right: [f32 ; 3],
direction: String,
}
impl Anaglyph {
fn get(&self, i: usize) -> (u8, u8) {
if self.direction==String::from("bottomright") {
let val1 = self.in_buf[i + 3 * (self.offset_y*self.in_x + self.offset_x * (i/(self.out_x * 3) + 1))];
let val2 = self.in_buf[i + 3 * (self.offset_x * i/(self.out_x * 3))];
(val1, val2)
}
else if self.direction==String::from("topright") {
let val1 = self.in_buf[i + 3 * (self.offset_x * (i/(self.out_x * 3) + 1))];
let val2 = self.in_buf[i + 3 * (self.offset_y*self.in_x + self.offset_x * i/(self.out_x * 3))];
(val1, val2)
}
else if self.direction==String::from("bottomleft") {
let val1 = self.in_buf[i + 3 * (self.offset_y*self.in_x + self.offset_x * i/(self.out_x * 3))];
let val2 = self.in_buf[i + 3 * (self.offset_x * (i/(self.out_x * 3) + 1))];
(val1, val2)
}
else {
let val1 = self.in_buf[i + 3 * (self.offset_x * i/(self.out_x * 3))];
let val2 = self.in_buf[i + 3 * (self.offset_y*self.in_x + self.offset_x * (i/(self.out_x * 3) + 1))];
(val1, val2)
}
}
fn fill(&mut self, out_buf: &mut Vec<u8>) {
let mut v1: u8;
let mut v2: u8;
for (i, byte) in out_buf.iter_mut().enumerate() {
(v1, v2) = self.get(i);
*byte = ((v1 as f32*self.color_left[i%3]) * 0.5 + (v2 as f32*self.color_right[i%3]) * 0.5) as u8;
}
}
}
#[cfg(test)]
mod tests {
use std::fs::{File, remove_file};
use super::*;
#[test]
fn division() {
assert!(9/5==1);
}
#[test]
fn output_file_center() {
let _ = remove_file("output_center.png");
create("bao-menglong-unsplash.jpg", "output_center.png", 0, 0, Coloring::Colorcode3D);
File::open("output_center.png").unwrap();
}
#[test]
fn output_file_bottomright() {
let _ = remove_file("output_bottomright.png");
create("bao-menglong-unsplash.jpg", "output_bottomright.png", 100, 20, Coloring::RedCyan);
File::open("output_bottomright.png").unwrap();
}
#[test]
fn output_file_topright() {
let _ = remove_file("output_topright.png");
create("bao-menglong-unsplash.jpg", "output_topright.png", 70, -14, Coloring::RedGreen);
File::open("output_topright.png").unwrap();
}
#[test]
fn output_file_bottomleft() {
let _ = remove_file("output_bottomleft.png");
create("bao-menglong-unsplash.jpg", "output_bottomleft.png", -30, 8, Coloring::Anachrome);
File::open("output_bottomleft.png").unwrap();
}
#[test]
fn output_file_topleft() {
let _ = remove_file("output_topleft.png");
create("bao-menglong-unsplash.jpg", "output_topleft.png", -10, -2, Coloring::Trioscopic);
File::open("output_topleft.png").unwrap();
}
}