use crate::colors::Colors;
use crate::io::IO;
use crate::pixel_color;
use crate::validator;
use image::GenericImageView;
use rand::Rng;
pub fn bottom_to_top_global(io: IO, proba: i32, colors: Vec<Colors>) {
let slim_global = SlimGlobal { colors, io, proba };
slim_global.validate_attributes();
slim_global.bottom_to_top()
}
pub fn left_to_right_global(io: IO, proba: i32, colors: Vec<Colors>) {
let slim_global = SlimGlobal { colors, io, proba };
slim_global.validate_attributes();
slim_global.left_to_right()
}
pub fn right_to_left_global(io: IO, proba: i32, colors: Vec<Colors>) {
let slim_global = SlimGlobal { colors, io, proba };
slim_global.validate_attributes();
slim_global.right_to_left()
}
pub fn top_to_bottom_global(io: IO, proba: i32, colors: Vec<Colors>) {
let slim_global = SlimGlobal { colors, io, proba };
slim_global.validate_attributes();
slim_global.top_to_bottom()
}
pub fn bottom_to_top_per_color(io: IO, colors_proba: Vec<(Colors, i32)>) {
let slim_per_color = SlimPerColor { io, colors_proba };
slim_per_color.bottom_to_top()
}
pub fn left_to_right_per_color(io: IO, colors_proba: Vec<(Colors, i32)>) {
let slim_per_color = SlimPerColor { io, colors_proba };
slim_per_color.left_to_right()
}
pub fn right_to_left_per_color(io: IO, colors_proba: Vec<(Colors, i32)>) {
let slim_per_color = SlimPerColor { io, colors_proba };
slim_per_color.right_to_left()
}
pub fn top_to_bottom_per_color(io: IO, colors_proba: Vec<(Colors, i32)>) {
let slim_per_color = SlimPerColor { io, colors_proba };
slim_per_color.top_to_bottom()
}
struct SlimGlobal<'a> {
colors: Vec<Colors>,
io: IO<'a>,
proba: i32,
}
struct SlimPerColor<'a> {
io: IO<'a>,
colors_proba: Vec<(Colors, i32)>,
}
trait ProbabilityCheck {
fn color_to_glitch(&self, pixel_color: Colors) -> bool;
fn probability_reached(&self, p: image::Rgba<u8>) -> bool;
}
impl<'a> ProbabilityCheck for SlimGlobal<'a> {
fn color_to_glitch(&self, pixel_color: Colors) -> bool {
self.colors.contains(&pixel_color)
}
fn probability_reached(&self, p: image::Rgba<u8>) -> bool {
let pixel_color = pixel_color::get_pixel_color(p);
let rng = rand::thread_rng().gen_range(0..100);
!self.color_to_glitch(pixel_color) || rng > self.proba
}
}
impl<'a> ProbabilityCheck for SlimPerColor<'a> {
fn color_to_glitch(&self, pixel_color: Colors) -> bool {
let color_proba = self.colors_proba.iter().filter(|cp| cp.0 == pixel_color);
let last_value = color_proba.last().unwrap_or(&(Colors::White, 0));
let rng = rand::thread_rng().gen_range(0..100);
let proba = last_value.1;
rng > proba
}
fn probability_reached(&self, p: image::Rgba<u8>) -> bool {
let pixel_color = pixel_color::get_pixel_color(p);
self.color_to_glitch(pixel_color)
}
}
impl<'a> SlimGlobal<'a> {
fn bottom_to_top(&self) {
let mut new_img = image::ImageBuffer::new(self.io.in_img.width(), self.io.in_img.height());
for w in 0..(self.io.in_img.width()) {
let mut tested_pixel = self.io.in_img.get_pixel(w, self.io.in_img.height() - 1);
for h in 0..(self.io.in_img.height() - 1) {
let inverted_h = self.io.in_img.height() - 2 - h;
if self.probability_reached(tested_pixel) {
new_img.put_pixel(w, inverted_h, self.io.in_img.get_pixel(w, inverted_h + 1));
tested_pixel = self.io.in_img.get_pixel(w, inverted_h);
} else {
new_img.put_pixel(w, inverted_h, tested_pixel);
}
}
}
new_img.save(self.io.out_img).unwrap();
}
fn left_to_right(&self) {
let mut new_img = image::ImageBuffer::new(self.io.in_img.width(), self.io.in_img.height());
for h in 0..(self.io.in_img.height()) {
let mut tested_pixel = self.io.in_img.get_pixel(0, h);
for w in 1..(self.io.in_img.width()) {
if self.probability_reached(tested_pixel) {
new_img.put_pixel(w, h, self.io.in_img.get_pixel(w, h));
tested_pixel = self.io.in_img.get_pixel(w, h);
} else {
new_img.put_pixel(w, h, tested_pixel);
}
}
}
new_img.save(self.io.out_img).unwrap();
}
fn right_to_left(&self) {
let mut new_img = image::ImageBuffer::new(self.io.in_img.width(), self.io.in_img.height());
for h in 0..(self.io.in_img.height()) {
let mut tested_pixel = self.io.in_img.get_pixel(self.io.in_img.width() - 1, h);
for w in 0..(self.io.in_img.width() - 1) {
let inverted_w = self.io.in_img.width() - 2 - w;
if self.probability_reached(tested_pixel) {
new_img.put_pixel(inverted_w, h, self.io.in_img.get_pixel(inverted_w + 1, h));
tested_pixel = self.io.in_img.get_pixel(inverted_w, h);
} else {
new_img.put_pixel(inverted_w, h, tested_pixel);
}
}
}
new_img.save(self.io.out_img).unwrap();
}
fn top_to_bottom(&self) {
let mut new_img = image::ImageBuffer::new(self.io.in_img.width(), self.io.in_img.height());
for w in 0..(self.io.in_img.width()) {
let mut tested_pixel = self.io.in_img.get_pixel(w, 0);
for h in 1..(self.io.in_img.height()) {
if self.probability_reached(tested_pixel) {
new_img.put_pixel(w, h, self.io.in_img.get_pixel(w, h));
tested_pixel = self.io.in_img.get_pixel(w, h);
} else {
new_img.put_pixel(w, h, tested_pixel);
}
}
}
new_img.save(self.io.out_img).unwrap();
}
fn validate_attributes(&self) {
validator::percent("probability", self.proba);
}
}
impl<'a> SlimPerColor<'a> {
fn bottom_to_top(&self) {
let mut new_img = image::ImageBuffer::new(self.io.in_img.width(), self.io.in_img.height());
for w in 0..(self.io.in_img.width()) {
let mut tested_pixel = self.io.in_img.get_pixel(w, self.io.in_img.height() - 1);
for h in 0..(self.io.in_img.height() - 1) {
let inverted_h = self.io.in_img.height() - 2 - h;
if self.probability_reached(tested_pixel) {
new_img.put_pixel(w, inverted_h, self.io.in_img.get_pixel(w, inverted_h + 1));
tested_pixel = self.io.in_img.get_pixel(w, inverted_h);
} else {
new_img.put_pixel(w, inverted_h, tested_pixel);
}
}
}
new_img.save(self.io.out_img).unwrap();
}
fn left_to_right(&self) {
let mut new_img = image::ImageBuffer::new(self.io.in_img.width(), self.io.in_img.height());
for h in 0..(self.io.in_img.height()) {
let mut tested_pixel = self.io.in_img.get_pixel(0, h);
for w in 1..(self.io.in_img.width()) {
if self.probability_reached(tested_pixel) {
new_img.put_pixel(w, h, self.io.in_img.get_pixel(w, h));
tested_pixel = self.io.in_img.get_pixel(w, h);
} else {
new_img.put_pixel(w, h, tested_pixel);
}
}
}
new_img.save(self.io.out_img).unwrap();
}
fn right_to_left(&self) {
let mut new_img = image::ImageBuffer::new(self.io.in_img.width(), self.io.in_img.height());
for h in 0..(self.io.in_img.height()) {
let mut tested_pixel = self.io.in_img.get_pixel(self.io.in_img.width() - 1, h);
for w in 0..(self.io.in_img.width() - 1) {
let inverted_w = self.io.in_img.width() - 2 - w;
if self.probability_reached(tested_pixel) {
new_img.put_pixel(inverted_w, h, self.io.in_img.get_pixel(inverted_w + 1, h));
tested_pixel = self.io.in_img.get_pixel(inverted_w, h);
} else {
new_img.put_pixel(inverted_w, h, tested_pixel);
}
}
}
new_img.save(self.io.out_img).unwrap();
}
fn top_to_bottom(&self) {
let mut new_img = image::ImageBuffer::new(self.io.in_img.width(), self.io.in_img.height());
for w in 0..(self.io.in_img.width()) {
let mut tested_pixel = self.io.in_img.get_pixel(w, 0);
for h in 1..(self.io.in_img.height()) {
if self.probability_reached(tested_pixel) {
new_img.put_pixel(w, h, self.io.in_img.get_pixel(w, h));
tested_pixel = self.io.in_img.get_pixel(w, h);
} else {
new_img.put_pixel(w, h, tested_pixel);
}
}
}
new_img.save(self.io.out_img).unwrap();
}
}