use crate::error::*;
pub mod lowlevel;
use log::warn;
use lowlevel::*;
use std::borrow::Cow;
use std::collections::HashMap;
use std::fs::File;
use std::io::{self, Read};
use std::path::Path;
use url::Url;
pub struct ImageOutput<'a> {
data: &'a [u8],
_converter: ImageConverter,
}
pub struct ImageApplication {
_guard: ImageGuard,
}
impl ImageApplication {
pub fn new() -> Result<ImageApplication> {
image_init().map(|guard| ImageApplication { _guard: guard })
}
pub fn builder(&self) -> ImageBuilder {
ImageBuilder { gs: HashMap::new() }
}
}
pub enum ImageFormat {
Jpg,
Png,
Bmp,
Svg,
}
impl ImageFormat {
fn value(&self) -> &'static str {
use ImageFormat::*;
match self {
Jpg => "jpg",
Png => "png",
Bmp => "bmp",
Svg => "svg",
}
}
}
#[derive(Clone)]
pub struct ImageBuilder {
gs: HashMap<&'static str, Cow<'static, str>>,
}
impl ImageBuilder {
pub fn screen_width(&mut self, screen_width: u32) -> &mut ImageBuilder {
self.gs
.insert("screenWidth", screen_width.to_string().into());
self
}
pub fn image_quality(&mut self, image_quality: u32) -> &mut ImageBuilder {
self.gs
.insert("imageQuality", image_quality.to_string().into());
self
}
pub fn transparent(&mut self, transparent: bool) -> &mut ImageBuilder {
self.gs
.insert("transparent", transparent.to_string().into());
self
}
pub fn format(&mut self, format: ImageFormat) -> &mut ImageBuilder {
self.gs.insert("fmt", format.value().into());
self
}
pub unsafe fn global_setting<S: Into<Cow<'static, str>>>(
&mut self,
name: &'static str,
value: S,
) -> &mut ImageBuilder {
self.gs.insert(name, value.into());
self
}
pub fn build_from_url<'a, 'b>(&'a mut self, url: &Url) -> Result<ImageOutput<'b>> {
let mut global = self.global_settings()?;
unsafe {
global.set("in", &*url.as_str())?;
}
let converter = global.create_converter();
converter.convert()
}
pub fn build_from_path<'a, 'b, P: AsRef<Path>>(
&'a mut self,
path: P,
) -> Result<ImageOutput<'b>> {
let path = path.as_ref();
if !path.is_file() {
warn!("the file {} does not exist", path.to_string_lossy());
return Err(Error::GlobalSettingFailure(
"in".to_string(),
path.to_string_lossy().to_string(),
));
}
let mut global = self.global_settings()?;
unsafe {
global.set("in", &path.to_string_lossy())?;
}
let converter = global.create_converter();
converter.convert()
}
pub fn global_settings(&self) -> Result<ImageGlobalSettings> {
let mut global = ImageGlobalSettings::new()?;
for (ref name, ref val) in &self.gs {
unsafe { global.set(name, &val) }?;
}
Ok(global)
}
}
impl<'a> ImageOutput<'a> {
pub fn save<P: AsRef<Path>>(&mut self, path: P) -> io::Result<File> {
let mut file = File::create(path)?;
let _ = io::copy(self, &mut file)?;
Ok(file)
}
}
impl<'a> Read for ImageOutput<'a> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.data.read(buf)
}
}
impl<'a> std::fmt::Debug for ImageOutput<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
self.data.fmt(f)
}
}