pub use self::sub_image::*;
pub use self::pixel::*;
pub use self::from_impl::*;
pub use self::pixel_iter::*;
mod sub_image;
mod pixel;
mod from_impl;
mod pixel_iter;
use crate::error;
#[derive(Debug, Clone, PartialEq)]
pub struct Image<T: Number> {
info: ImageInfo,
data: Vec<T>,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ImageInfo {
pub width: u32,
pub height: u32,
pub channels: u8,
pub alpha: bool,
}
pub trait Number:
std::marker::Copy
+ std::fmt::Display
+ std::cmp::PartialEq
+ std::cmp::PartialOrd
+ std::marker::Sync
+ std::marker::Send
+ std::ops::Add<Output=Self>
+ std::ops::Sub<Output=Self>
+ std::ops::Mul<Output=Self>
+ std::ops::Div<Output=Self>
+ std::ops::Rem<Output=Self>
+ std::ops::AddAssign
+ std::ops::SubAssign
+ std::ops::MulAssign
+ std::ops::DivAssign
+ std::ops::RemAssign
+ From<u8>
where Self: std::marker::Sized {}
impl<T> Number for T
where T:
std::marker::Copy
+ std::fmt::Display
+ std::cmp::PartialEq
+ std::cmp::PartialOrd
+ std::marker::Sync
+ std::marker::Send
+ std::ops::Add<Output=T>
+ std::ops::Sub<Output=T>
+ std::ops::Mul<Output=T>
+ std::ops::Div<Output=T>
+ std::ops::Rem<Output=T>
+ std::ops::AddAssign
+ std::ops::SubAssign
+ std::ops::MulAssign
+ std::ops::DivAssign
+ std::ops::RemAssign
+ From<u8> {}
pub trait BaseImage<T: Number> {
fn info(&self) -> ImageInfo;
fn get_pixel(&self, x: u32, y: u32) -> &[T];
}
impl ImageInfo {
pub fn new(width: u32, height: u32, channels: u8, alpha: bool) -> Self {
ImageInfo { width, height, channels, alpha }
}
pub fn wh(&self) -> (u32, u32) {
(self.width, self.height)
}
pub fn whc(&self) -> (u32, u32, u8) {
(self.width, self.height, self.channels)
}
pub fn whca(&self) -> (u32, u32, u8, bool) {
(self.width, self.height, self.channels, self.alpha)
}
pub fn channels_non_alpha(&self) -> u8 {
if self.alpha {
self.channels - 1
} else {
self.channels
}
}
pub fn size(&self) -> u32 {
self.width * self.height
}
pub fn full_size(&self) -> u32 {
self.width * self.height * (self.channels as u32)
}
}
impl std::fmt::Display for ImageInfo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "width: {}\nheight: {}\nchannels: {}\nalpha: {}", self.width, self.height, self.channels, self.alpha)
}
}
impl<T: Number> Image<T> {
pub fn from_slice(width: u32, height: u32, channels: u8, alpha: bool, data: &[T]) -> Self {
Image {
info: ImageInfo{ width, height, channels, alpha },
data: data.to_vec(),
}
}
pub fn from_vec(width: u32, height: u32, channels: u8, alpha: bool, data: Vec<T>) -> Self {
Image {
info: ImageInfo{ width, height, channels, alpha },
data,
}
}
pub fn from_vec_of_vec(width: u32, height: u32, channels: u8, alpha: bool, data: Vec<Vec<T>>) -> Self {
let mut data_vec = Vec::with_capacity((width * height * channels as u32) as usize);
for vec in &data {
data_vec.extend_from_slice(vec)
}
Image {
info: ImageInfo{ width, height, channels, alpha },
data: data_vec,
}
}
pub fn from_vec_of_slice(width: u32, height: u32, channels: u8, alpha: bool, data: Vec<&[T]>) -> Self {
let mut data_vec = Vec::with_capacity((width * height * channels as u32) as usize);
for vec in data {
data_vec.extend_from_slice(vec)
}
Image {
info: ImageInfo{ width, height, channels, alpha },
data: data_vec,
}
}
pub fn blank(info: ImageInfo) -> Self {
Image {
info,
data: vec![0.into(); info.full_size() as usize],
}
}
pub fn empty(info: ImageInfo) -> Self {
Image {
info,
data: Vec::with_capacity(info.full_size() as usize),
}
}
pub fn index(&self, x: u32, y: u32) -> usize {
((y * self.info.width + x) * self.info.channels as u32) as usize
}
pub fn data(&self) -> &[T] {
&self.data[..]
}
pub fn data_mut(&mut self) -> &mut [T] {
&mut self.data[..]
}
pub fn get_pixel_unchecked(&self, x: u32, y: u32) -> &[T] {
&self[(y * self.info.width + x) as usize]
}
pub fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut [T] {
error::check_xy(x, y, self.info.width, self.info.height);
let start = self.index(x, y);
&mut self.data[start..(start + self.info.channels as usize)]
}
pub fn get_pixel_mut_unchecked(&mut self, x: u32, y: u32) -> &mut [T] {
let index = (y * self.info.width + x) as usize;
&mut self[index]
}
pub fn get_subimage(&self, x: u32, y: u32, width: u32, height: u32) -> SubImage<T> {
error::check_xy(x, y, self.info.width, self.info.height);
let mut data = Vec::new();
for i in x..(x + width) {
for j in y..(y + height) {
data.push(self.get_pixel(i, j));
}
}
SubImage::new(width, height, self.info.channels, self.info.alpha, data)
}
pub fn get_neighborhood_1d(&self, x: u32, y: u32, size: u32, is_vert: bool) -> SubImage<T> {
error::check_xy(x, y, self.info.width, self.info.height);
let mut data = Vec::new();
if is_vert {
let start_y = (y as i32) - (size as i32) / 2;
for i in 0..size {
let mut curr_y = start_y + (i as i32);
if curr_y < 0 || curr_y >= self.info.height as i32 { curr_y = y as i32 };
data.push(self.get_pixel(x, curr_y as u32));
}
SubImage::new(1, size, self.info.channels, self.info.alpha, data)
} else {
let start_x = (x as i32) - (size as i32) / 2;
for i in 0..size {
let mut curr_x = start_x + (i as i32);
if curr_x < 0 || curr_x >= self.info.width as i32 { curr_x = x as i32 };
data.push(self.get_pixel(curr_x as u32, y));
}
SubImage::new(size, 1, self.info.channels, self.info.alpha, data)
}
}
pub fn get_neighborhood_2d(&self, x: u32, y: u32, size: u32) -> SubImage<T> {
error::check_xy(x, y, self.info.width, self.info.height);
let start_x = (x as i32) - (size as i32) / 2;
let start_y = (y as i32) - (size as i32) / 2;
let mut data = Vec::new();
for i in 0..size {
for j in 0..size {
let mut curr_x = start_x + (j as i32);
let mut curr_y = start_y + (i as i32);
if curr_x < 0 || curr_x >= self.info.width as i32 { curr_x = x as i32 };
if curr_y < 0 || curr_y >= self.info.height as i32 { curr_y = y as i32 };
data.push(self.get_pixel(curr_x as u32, curr_y as u32));
}
}
SubImage::new(size, size, self.info.channels, self.info.alpha, data)
}
pub fn set_pixel(&mut self, x: u32, y: u32, pixel: &[T]) {
error::check_channels(self.info.channels, pixel.len());
error::check_xy(x, y, self.info.width, self.info.height);
let start = self.index(x, y);
for i in 0..(self.info.channels as usize) {
self.data[i + start] = pixel[i];
}
}
pub fn set_pixel_indexed(&mut self, index: usize, pixel: &[T]) {
error::check_channels(self.info.channels, pixel.len());
let start = index * self.info.channels as usize;
for i in 0..(self.info.channels as usize) {
self.data[start + i] = pixel[i];
}
}
pub fn map_pixels<S: Number, F>(&self, f: F) -> Image<S>
where F: Fn(&[T]) -> Vec<S> {
let mut data= Vec::new();
for i in 0..(self.info.size() as usize) {
data.append(&mut f(&self[i]));
}
let channels = (data.len() as u32 / self.info.size()) as u8;
Image {
info: ImageInfo {
width: self.info.width,
height: self.info.height,
channels,
alpha: self.info.alpha
},
data,
}
}
pub fn map_pixels_if_alpha<S: Number, F, G>(&self, f: F, g: G) -> Image<S>
where F: Fn(&[T]) -> Vec<S>,
G: Fn(T) -> S {
if !self.info.alpha {
return self.map_pixels(f);
}
let mut data = Vec::new();
for i in 0..(self.info.size() as usize) {
let mut v = f(self[i].channels_without_alpha());
v.push(g(self[i].alpha()));
data.append(&mut v);
}
let channels = (data.len() as u32 / self.info.size()) as u8;
Image {
info: ImageInfo {
width: self.info.width,
height: self.info.height,
channels,
alpha: self.info.alpha
},
data,
}
}
pub fn map_channels<S: Number, F>(&self, f: F) -> Image<S>
where F: Fn(T) -> S {
let mut data = Vec::new();
for i in 0..(self.info.full_size() as usize) {
data.push(f(self.data[i]));
}
Image {
info: self.info,
data,
}
}
pub fn map_channels_if_alpha<S: Number, F, G>(&self, f: F, g: G) -> Image<S>
where F: Fn(T) -> S,
G: Fn(T) -> S {
if !self.info.alpha {
return self.map_channels(f);
}
let mut data = Vec::new();
for i in 0..(self.info.size() as usize) {
data.append(&mut self[i].map_alpha(&f, &g));
}
Image {
info: self.info,
data,
}
}
pub fn apply_pixels<F>(&mut self, f: F)
where F: Fn(&[T]) -> Vec<T> {
for i in 0..self.info.size() as usize {
self.set_pixel_indexed(i, f(&self[i]).as_slice());
}
}
pub fn apply_pixels_if_alpha<F, G>(&mut self, f: F, g: G)
where F: Fn(&[T]) -> Vec<T>,
G: Fn(T) -> T {
if !self.info.alpha {
self.apply_pixels(f);
return;
}
for i in 0..(self.info.size() as usize) {
let mut v = f(self[i].channels_without_alpha());
v.push(g(self[i].alpha()));
self.set_pixel_indexed(i, v.as_slice());
}
}
pub fn apply_channels<F>(&mut self, f: F)
where F: Fn(T) -> T {
for i in 0..(self.info.full_size() as usize) {
self.data[i] = f(self.data[i]);
}
}
pub fn apply_channels_if_alpha<F, G>(&mut self, f: F, g: G)
where F: Fn(T) -> T,
G: Fn(T) -> T {
if !self.info.alpha {
self.apply_channels(f);
return;
}
for i in 0..(self.info.size() as usize) {
self[i].apply_alpha(&f, &g);
}
}
pub fn edit_channel<F>(&mut self, f: F, index: usize)
where F: Fn(T) -> T {
for i in (index..(self.info.full_size() as usize)).step_by(self.info.channels as usize) {
self.data[i] = f(self.data[i]);
}
}
}
impl<T: Number> BaseImage<T> for Image<T> {
fn info(&self) -> ImageInfo {
self.info
}
fn get_pixel(&self, x: u32, y: u32) -> &[T] {
error::check_xy(x, y, self.info.width, self.info.height);
&self[(y * self.info.width + x) as usize]
}
}
impl<T: Number> std::ops::Index<usize> for Image<T> {
type Output = [T];
fn index(&self, i: usize) -> &Self::Output {
let start = i * (self.info.channels as usize);
&self.data[start..(start + self.info.channels as usize)]
}
}
impl<T: Number> std::ops::IndexMut<usize> for Image<T> {
fn index_mut(&mut self, i: usize) -> &mut Self::Output {
let start = i * (self.info.channels as usize);
&mut self.data[start..(start + self.info.channels as usize)]
}
}