#![allow(deprecated)]
use std::io::Cursor;
use crate::{AnyRes, Result};
use image::io::Reader;
pub use image::{ColorType, DynamicImage, GenericImageView, ImageFormat};
#[derive(Debug)]
pub enum ImageSource<'a> {
File(String),
Memory(&'a [u8]),
Url(String),
Database(u64),
NetworkStream(Vec<u8>),
}
impl<'a> ImageSource<'a> {
pub fn to_image(self) -> Result<DynamicImage> {
Ok(match self {
ImageSource::File(file_path) => image::open(file_path).map_err(|e| e.to_string())?,
ImageSource::Memory(image_data) => {
image::load_from_memory(&image_data).map_err(|e| e.to_string())?
}
ImageSource::Url(_url) => {
#[cfg(not(feature = "http-blocking"))]
return Err("Need add feature = http-blocking".into());
#[cfg(feature = "http-blocking")]
{
let response = reqwest::blocking::get(&_url).map_err(|e| e.to_string())?;
let image_data = response.bytes().map_err(|e| e.to_string())?.to_vec();
image::load_from_memory(&image_data).map_err(|e| e.to_string())?
}
}
ImageSource::Database(_image_id) => {
return Err("Database image loading is not implemented yet".into());
}
ImageSource::NetworkStream(bytes) => {
let reader = std::io::Cursor::new(bytes);
Reader::new(reader)
.with_guessed_format().any()?
.decode()
.map_err(|e| e.to_string())?
}
})
}
pub const unsafe fn from_raw_parts<T>(buf_ptr: *const T, len: usize) -> &'a [T] {
std::slice::from_raw_parts(buf_ptr, len)
}
pub unsafe fn from_raw_parts_image<T>(buf_ptr: *const T, len: usize) -> Self {
Self::Memory(Self::from_raw_parts(buf_ptr as *const u8, len))
}
pub unsafe fn from_raw_parts_reader<T>(
buf_ptr: *const T,
len: usize,
) -> Result<Reader<Cursor<&'a [u8]>>> {
let x = Reader::new(std::io::Cursor::new(Self::from_raw_parts(
buf_ptr as *const u8,
len,
)))
.with_guessed_format().any()?;
Ok(x)
}
#[cfg(feature = "base64")]
pub unsafe fn from_raw_parts_base64<T>(buf_ptr: *const T, len: usize) -> Result<String> {
let reader = Self::from_raw_parts_reader(buf_ptr, len)?;
let iformat = reader.format().res()?;
let image = reader.decode().map_err(|e| e.to_string())?;
Self::image_to_base64(&image, iformat)
}
pub fn to_ptr(self) -> Result<(*const u8, usize)> {
let image = self.to_image()?;
Self::image_to_ptr(image)
}
pub fn image_write_bytes(
image: &DynamicImage,
iformat: image::ImageFormat,
) -> Result<Cursor<Vec<u8>>> {
let mut cursor = Cursor::new(Vec::new());
image
.write_to(&mut cursor, iformat)
.map_err(|e| e.to_string())?;
Ok(cursor)
}
#[cfg(feature = "base64")]
pub fn to_base64(self, iformat: ImageFormat) -> Result<String> {
let image = self.to_image()?;
Self::image_to_base64(&image, iformat)
}
#[cfg(feature = "base64")]
pub fn image_to_base64(image: &DynamicImage, iformat: ImageFormat) -> Result<String> {
Ok(crate::algorithm::base64::encode(
Self::image_write_bytes(image, iformat)?.into_inner(),
))
}
pub fn image_to_ptr(image: DynamicImage) -> Result<(*const u8, usize)> {
let (width, height) = image.dimensions();
let color_type = image.color();
let (ptr, pixel_size) = match color_type {
ColorType::Rgb8 => (image.into_rgb8().as_ptr(), 3),
ColorType::Rgba8 => (image.into_rgba8().as_ptr(), 4),
_ => return Err("ColorType未知类型".into()),
};
let total_size = (width * height) as usize * pixel_size;
Ok((ptr, total_size))
}
}