use std::{io::Cursor, path::Path};
use image::{imageops::FilterType, metadata::Orientation, DynamicImage, ImageFormat, ImageReader};
use serde::{Deserialize, Serialize};
use crate::model::StofData;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Image {
pub raw: Vec<u8>,
#[serde(skip)]
pub dynamic: Option<DynamicImage>,
}
#[typetag::serde(name = "Image")]
impl StofData for Image {}
impl Image {
#[allow(unused)]
pub fn from_file<P>(path: P) -> Result<Self, String>
where P: AsRef<Path>,
{
let res = ImageReader::open(path);
match res {
Ok(reader) => {
let decoded = reader.decode();
match decoded {
Ok(image) => {
let mut bytes: Vec<u8> = Vec::new();
if let Err(error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Png) {
return Err(error.to_string());
}
Ok(Self {
raw: bytes,
dynamic: Some(image),
})
},
Err(error) => {
Err(error.to_string())
}
}
},
Err(error) => {
Err(error.to_string())
}
}
}
pub fn from_bytes(bytes: Vec<u8>) -> Result<Self, String> {
if let Ok(mut reader) = ImageReader::new(Cursor::new(bytes)).with_guessed_format() {
if reader.format().is_none() {
reader.set_format(ImageFormat::Png); }
if let Ok(image) = reader.decode() {
let mut bytes: Vec<u8> = Vec::new();
if let Err(error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Png) {
return Err(error.to_string());
}
return Ok(Self {
raw: bytes,
dynamic: Some(image),
});
}
}
Err("Could not convert bytes into an image".into())
}
pub fn ensure_dynamic(&mut self) -> bool {
if self.dynamic.is_some() {
return true;
} else if let Ok(mut reader) = ImageReader::new(Cursor::new(&self.raw)).with_guessed_format() {
if reader.format().is_none() {
reader.set_format(ImageFormat::Png); }
if let Ok(image) = reader.decode() {
self.dynamic = Some(image);
return true;
}
}
false
}
pub fn save_image(&mut self) -> bool {
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Png) {
return false;
}
self.raw = bytes;
return true;
}
false
}
pub fn png_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Png) {
return None;
}
return Some(bytes);
}
None
}
pub fn jpeg_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Jpeg) {
return None;
}
return Some(bytes);
}
None
}
pub fn gif_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Gif) {
return None;
}
return Some(bytes);
}
None
}
pub fn webp_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::WebP) {
return None;
}
return Some(bytes);
}
None
}
#[allow(unused)]
pub fn pnm_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Pnm) {
return None;
}
return Some(bytes);
}
None
}
pub fn tiff_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Tiff) {
return None;
}
return Some(bytes);
}
None
}
#[allow(unused)]
pub fn tga_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Tga) {
return None;
}
return Some(bytes);
}
None
}
#[allow(unused)]
pub fn dds_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Dds) {
return None;
}
return Some(bytes);
}
None
}
pub fn bmp_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Bmp) {
return None;
}
return Some(bytes);
}
None
}
pub fn ico_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Ico) {
return None;
}
return Some(bytes);
}
None
}
#[allow(unused)]
pub fn hdr_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Hdr) {
return None;
}
return Some(bytes);
}
None
}
#[allow(unused)]
pub fn open_exr_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::OpenExr) {
return None;
}
return Some(bytes);
}
None
}
#[allow(unused)]
pub fn farbfeld_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Farbfeld) {
return None;
}
return Some(bytes);
}
None
}
#[allow(unused)]
pub fn avif_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Avif) {
return None;
}
return Some(bytes);
}
None
}
#[allow(unused)]
pub fn qoi_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Qoi) {
return None;
}
return Some(bytes);
}
None
}
#[allow(unused)]
pub fn pcx_bytes(&mut self) -> Option<Vec<u8>> {
if !self.ensure_dynamic() { return None; }
if let Some(image) = &self.dynamic {
let mut bytes: Vec<u8> = Vec::new();
if let Err(_error) = image.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Pcx) {
return None;
}
return Some(bytes);
}
None
}
pub fn width(&mut self) -> u32 {
if !self.ensure_dynamic() { return 0; }
if let Some(image) = &self.dynamic {
return image.width();
}
0
}
pub fn height(&mut self) -> u32 {
if !self.ensure_dynamic() { return 0; }
if let Some(image) = &self.dynamic {
return image.height();
}
0
}
pub fn grayscale(&mut self) {
if !self.ensure_dynamic() { return; }
let mut grayscale = None;
if let Some(image) = &self.dynamic {
grayscale = Some(image.grayscale());
}
if let Some(image) = grayscale {
self.dynamic = Some(image);
self.save_image();
}
}
pub fn invert(&mut self) {
if !self.ensure_dynamic() { return; }
if let Some(image) = &mut self.dynamic {
image.invert();
self.save_image();
}
}
pub fn resize(&mut self, width: u32, height: u32, filter: FilterType) {
if !self.ensure_dynamic() { return; }
let mut resized = None;
if let Some(image) = &self.dynamic {
resized = Some(image.resize(width, height, filter));
}
if let Some(image) = resized {
self.dynamic = Some(image);
self.save_image();
}
}
pub fn resize_exact(&mut self, width: u32, height: u32, filter: FilterType) {
if !self.ensure_dynamic() { return; }
let mut resized = None;
if let Some(image) = &self.dynamic {
resized = Some(image.resize_exact(width, height, filter));
}
if let Some(image) = resized {
self.dynamic = Some(image);
self.save_image();
}
}
pub fn thumbnail(&mut self, width: u32, height: u32) {
if !self.ensure_dynamic() { return; }
let mut resized = None;
if let Some(image) = &self.dynamic {
resized = Some(image.thumbnail(width, height));
}
if let Some(image) = resized {
self.dynamic = Some(image);
self.save_image();
}
}
pub fn thumbnail_exact(&mut self, width: u32, height: u32) {
if !self.ensure_dynamic() { return; }
let mut resized = None;
if let Some(image) = &self.dynamic {
resized = Some(image.thumbnail_exact(width, height));
}
if let Some(image) = resized {
self.dynamic = Some(image);
self.save_image();
}
}
pub fn blur(&mut self, sigma: f32) {
if !self.ensure_dynamic() { return; }
let mut resized = None;
if let Some(image) = &self.dynamic {
resized = Some(image.blur(sigma));
}
if let Some(image) = resized {
self.dynamic = Some(image);
self.save_image();
}
}
pub fn fast_blur(&mut self, sigma: f32) {
if !self.ensure_dynamic() { return; }
let mut resized = None;
if let Some(image) = &self.dynamic {
resized = Some(image.fast_blur(sigma));
}
if let Some(image) = resized {
self.dynamic = Some(image);
self.save_image();
}
}
pub fn adjust_contrast(&mut self, contrast: f32) {
if !self.ensure_dynamic() { return; }
let mut altered = None;
if let Some(image) = &self.dynamic {
altered = Some(image.adjust_contrast(contrast));
}
if let Some(image) = altered {
self.dynamic = Some(image);
self.save_image();
}
}
pub fn brighten(&mut self, value: i32) {
if !self.ensure_dynamic() { return; }
let mut altered = None;
if let Some(image) = &self.dynamic {
altered = Some(image.brighten(value));
}
if let Some(image) = altered {
self.dynamic = Some(image);
self.save_image();
}
}
pub fn flip_vertical(&mut self) {
if !self.ensure_dynamic() { return; }
if let Some(image) = &mut self.dynamic {
image.apply_orientation(Orientation::FlipVertical);
self.save_image();
}
}
pub fn flip_horizontal(&mut self) {
if !self.ensure_dynamic() { return; }
if let Some(image) = &mut self.dynamic {
image.apply_orientation(Orientation::FlipHorizontal);
self.save_image();
}
}
pub fn rotate_90(&mut self) {
if !self.ensure_dynamic() { return; }
if let Some(image) = &mut self.dynamic {
image.apply_orientation(Orientation::Rotate90);
self.save_image();
}
}
pub fn rotate_180(&mut self) {
if !self.ensure_dynamic() { return; }
if let Some(image) = &mut self.dynamic {
image.apply_orientation(Orientation::Rotate180);
self.save_image();
}
}
pub fn rotate_270(&mut self) {
if !self.ensure_dynamic() { return; }
if let Some(image) = &mut self.dynamic {
image.apply_orientation(Orientation::Rotate270);
self.save_image();
}
}
}