use crate::io::IO;
use crate::pixel_color;
use crate::pixel_sorting::PixelSorting;
use image::GenericImageView;
pub fn bottom_to_top(
io: IO,
detection_type: i32,
detection_min: i32,
detection_max: i32,
multiple_range: bool,
detection_min_2: i32,
detection_max_2: i32,
sorting_by: i32,
) {
let pixel_sort = PixelSort {
io,
detection_type,
detection_max,
detection_min,
multiple_range,
detection_max_2,
detection_min_2,
sorting_by,
};
pixel_sort.bottom_to_top_sort()
}
pub fn left_to_right(
io: IO,
detection_type: i32,
detection_min: i32,
detection_max: i32,
multiple_range: bool,
detection_min_2: i32,
detection_max_2: i32,
sorting_by: i32,
) {
let pixel_sort = PixelSort {
io,
detection_type,
detection_max,
detection_min,
multiple_range,
detection_max_2,
detection_min_2,
sorting_by,
};
pixel_sort.left_to_right_sort()
}
pub fn right_to_left(
io: IO,
detection_type: i32,
detection_min: i32,
detection_max: i32,
multiple_range: bool,
detection_min_2: i32,
detection_max_2: i32,
sorting_by: i32,
) {
let pixel_sort = PixelSort {
io,
detection_type,
detection_max,
detection_min,
multiple_range,
detection_max_2,
detection_min_2,
sorting_by,
};
pixel_sort.right_to_left_sort()
}
pub fn top_to_bottom(
io: IO,
detection_type: i32,
detection_min: i32,
detection_max: i32,
multiple_range: bool,
detection_min_2: i32,
detection_max_2: i32,
sorting_by: i32,
) {
let pixel_sort = PixelSort {
io,
detection_type,
detection_max,
detection_min,
multiple_range,
detection_max_2,
detection_min_2,
sorting_by,
};
pixel_sort.top_to_bottom_sort()
}
struct PixelSort<'a> {
io: IO<'a>,
detection_type: i32,
detection_max: i32,
detection_min: i32,
multiple_range: bool,
detection_max_2: i32,
detection_min_2: i32,
sorting_by: i32,
}
impl<'a> PixelSort<'a> {
fn are_pixels_grouped(&self, p1: image::Rgba<u8>, p2: image::Rgba<u8>) -> bool {
if self.detection_type == 0 {
self.is_pixel_lightness_in_range(p1) && self.is_pixel_lightness_in_range(p2)
} else {
self.are_pixels_same_colors(p1, p2)
}
}
fn are_pixels_same_colors(&self, p1: image::Rgba<u8>, p2: image::Rgba<u8>) -> bool {
pixel_color::get_pixel_color(p1) == pixel_color::get_pixel_color(p2)
}
fn bottom_to_top_sort(&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() - 1) {
let mut strip = Vec::new();
let mut start_h = self.io.in_img.height() - 1;
strip.push(self.io.in_img.get_pixel(w, self.io.in_img.height() - 1));
for h in 1..(self.io.in_img.height() - 1) {
let previous_pixel = self.io.in_img.get_pixel(w, self.io.in_img.height() - h);
let current_pixel = self.io.in_img.get_pixel(w, self.io.in_img.height() - 1 - h);
if self.are_pixels_grouped(previous_pixel, current_pixel) {
strip.push(current_pixel);
} else {
let new_strip = self.sort_strip(&mut strip);
self.prepend_strip_to_image_vertically(&mut new_img, new_strip, start_h, w);
start_h = self.io.in_img.height() - 1 - h;
strip = Vec::new();
strip.push(current_pixel);
}
}
let new_strip = self.sort_strip(&mut strip);
self.prepend_strip_to_image_vertically(&mut new_img, new_strip, start_h, w);
}
new_img.save(self.io.out_img).unwrap();
}
fn is_pixel_lightness_in_range(&self, p: image::Rgba<u8>) -> bool {
let lig = pixel_color::get_pixel_lightness(p);
if self.multiple_range {
(lig / 5000.) > (self.detection_min as f32)
&& (lig / 5000.) < (self.detection_max as f32)
|| (lig / 5000.) > (self.detection_min_2 as f32)
&& (lig / 5000.) < (self.detection_max_2 as f32)
} else {
(lig / 5000.) > (self.detection_min as f32)
&& (lig / 5000.) < (self.detection_max as f32)
}
}
fn left_to_right_sort(&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() - 1) {
let mut strip = Vec::new();
let mut start_w = 0;
strip.push(self.io.in_img.get_pixel(0, h));
for w in 1..(self.io.in_img.width() - 1) {
let previous_pixel = self.io.in_img.get_pixel(w - 1, h);
let current_pixel = self.io.in_img.get_pixel(w, h);
if self.are_pixels_grouped(previous_pixel, current_pixel) {
strip.push(current_pixel);
} else {
let new_strip = self.sort_strip(&mut strip);
self.append_strip_to_image(&mut new_img, new_strip, h, start_w);
start_w = w + 1;
strip = Vec::new();
strip.push(current_pixel);
}
}
let new_strip = self.sort_strip(&mut strip);
self.append_strip_to_image(&mut new_img, new_strip, h, start_w);
}
new_img.save(self.io.out_img).unwrap();
}
fn right_to_left_sort(&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() - 1) {
let mut strip = Vec::new();
let mut start_w = self.io.in_img.width() - 1;
strip.push(self.io.in_img.get_pixel(self.io.in_img.width() - 1, h));
for w in 1..(self.io.in_img.width() - 1) {
let previous_pixel = self.io.in_img.get_pixel(self.io.in_img.width() - w, h);
let current_pixel = self.io.in_img.get_pixel(self.io.in_img.width() - 1 - w, h);
if self.are_pixels_grouped(previous_pixel, current_pixel) {
strip.push(current_pixel);
} else {
let new_strip = self.sort_strip(&mut strip);
self.prepend_strip_to_image(&mut new_img, new_strip, h, start_w);
start_w = self.io.in_img.width() - 1 - w;
strip = Vec::new();
strip.push(current_pixel);
}
}
let new_strip = self.sort_strip(&mut strip);
self.prepend_strip_to_image(&mut new_img, new_strip, h, start_w);
}
new_img.save(self.io.out_img).unwrap();
}
fn sort_strip<'b>(&self, strip: &'b mut Vec<image::Rgba<u8>>) -> &'b mut Vec<image::Rgba<u8>> {
if self.sorting_by == 0 {
self.sort_strip_by_hue(strip)
} else {
self.sort_strip_by_saturation(strip)
}
}
fn sort_strip_by_hue<'b>(
&self,
strip: &'b mut Vec<image::Rgba<u8>>,
) -> &'b mut Vec<image::Rgba<u8>> {
strip.sort_by(|a, b| {
pixel_color::get_pixel_hue(*a)
.partial_cmp(&pixel_color::get_pixel_hue(*b))
.unwrap()
});
strip
}
fn sort_strip_by_saturation<'b>(
&self,
strip: &'b mut Vec<image::Rgba<u8>>,
) -> &'b mut Vec<image::Rgba<u8>> {
strip.sort_by(|a, b| {
pixel_color::get_pixel_saturation(*a)
.partial_cmp(&pixel_color::get_pixel_saturation(*b))
.unwrap()
});
strip
}
fn top_to_bottom_sort(&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() - 1) {
let mut strip = Vec::new();
let mut start_h = 0;
strip.push(self.io.in_img.get_pixel(w, 0));
for h in 1..(self.io.in_img.height() - 1) {
let previous_pixel = self.io.in_img.get_pixel(w, h - 1);
let current_pixel = self.io.in_img.get_pixel(w, h);
if self.are_pixels_grouped(previous_pixel, current_pixel) {
strip.push(current_pixel);
} else {
let new_strip = self.sort_strip(&mut strip);
self.append_strip_to_image_vertically(&mut new_img, new_strip, start_h, w);
start_h = h + 1;
strip = Vec::new();
strip.push(current_pixel);
}
}
let new_strip = self.sort_strip(&mut strip);
self.append_strip_to_image_vertically(&mut new_img, new_strip, start_h, w);
}
new_img.save(self.io.out_img).unwrap();
}
}
impl<'a> PixelSorting for PixelSort<'a> {}