use std::fs;
use std::path::{Path, PathBuf};
use color_eyre::eyre::{self, Result};
use image::{ColorType, DynamicImage, ImageReader};
use ratatui::crossterm::terminal;
pub fn convert_image_ext<T>(image_path: T) -> Result<PathBuf>
where
T: AsRef<Path>,
{
let image_path = image_path.as_ref();
if !image_path.is_file() {
eyre::bail!("Image does not exist: {}", image_path.display());
}
let image_path = dunce::canonicalize(image_path)?;
let image_ext = image_path.extension().unwrap().to_str().unwrap();
if image_ext == "webp" {
return Ok(image_path);
}
let image = ImageReader::open(&image_path)?
.with_guessed_format()?
.decode()?;
match new_image_ext(&image) {
Ok(new_image_ext) => {
if image_ext != new_image_ext {
let new_image_path = image_path.with_extension(new_image_ext);
tracing::info!(
"Perform image format conversion: from `{}` to `{}`",
image_path.display(),
new_image_path.display()
);
if new_image_ext == "webp" {
novel_api::save_as_webp(&image, 75.0, &new_image_path)?;
} else {
image.save(&new_image_path)?;
}
Ok(new_image_path)
} else {
Ok(image_path)
}
}
Err(err) => {
tracing::error!("Failed to convert image: {err}");
Ok(image_path)
}
}
}
pub fn convert_image_file_stem<T, E>(image_path: T, new_image_stem: E) -> Result<PathBuf>
where
T: AsRef<Path>,
E: AsRef<str>,
{
let image_path = image_path.as_ref();
if !image_path.is_file() {
eyre::bail!("Image does not exist: {}", image_path.display());
}
let image_path = dunce::canonicalize(image_path)?;
let image_dir = image_path.parent().unwrap();
let image_file_stem = image_path.file_stem().unwrap().to_str().unwrap();
let image_ext = image_path.extension().unwrap().to_str().unwrap();
if new_image_stem.as_ref() != image_file_stem {
let new_image_path = image_dir.join(format!("{}.{image_ext}", new_image_stem.as_ref()));
tracing::info!(
"Perform image copy: from `{}` to `{}`",
image_path.display(),
new_image_path.display()
);
fs::copy(image_path, &new_image_path)?;
Ok(new_image_path)
} else {
Ok(image_path)
}
}
pub fn new_image_ext(image: &DynamicImage) -> Result<&'static str> {
match image.color() {
ColorType::Rgb8 | ColorType::Rgba8 => Ok("webp"),
ColorType::L8
| ColorType::L16
| ColorType::La8
| ColorType::La16
| ColorType::Rgb16
| ColorType::Rgba16 => Ok("png"),
other => eyre::bail!("This color type is not supported: {other:?}"),
}
}
pub fn terminal_size() -> (u16, u16) {
terminal::size().unwrap_or((80, 24))
}