Upgrade dependencies and use fast_image_resize
This commit is contained in:
parent
83fa2c6864
commit
4c598da07a
3 changed files with 1308 additions and 686 deletions
1908
Cargo.lock
generated
1908
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
11
Cargo.toml
11
Cargo.toml
|
@ -7,14 +7,15 @@ edition = "2021"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
simplelog = "0.12"
|
simplelog = "0.12"
|
||||||
wry = "0.20"
|
wry = "0.27"
|
||||||
native-dialog = "0.6"
|
native-dialog = "0.6"
|
||||||
rust-embed = "6"
|
rust-embed = "6"
|
||||||
base64 = "0.13"
|
base64 = "0.21"
|
||||||
directories = "4"
|
directories = "5"
|
||||||
clap = "3"
|
clap = "4"
|
||||||
warp = "0.3"
|
warp = "0.3"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
image = "0.24"
|
image = "0.24"
|
||||||
rexiv2 = "0.9"
|
rexiv2 = "0.10"
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
|
fast_image_resize = "2"
|
73
src/main.rs
73
src/main.rs
|
@ -1,14 +1,15 @@
|
||||||
#![windows_subsystem = "windows"]
|
#![windows_subsystem = "windows"]
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
use base64::Engine;
|
||||||
use clap::{Arg, Command};
|
use clap::{Arg, Command};
|
||||||
use image::{imageops::FilterType, io::Reader as ImageReader};
|
use image::{io::Reader as ImageReader, DynamicImage};
|
||||||
use log::info;
|
use log::info;
|
||||||
use native_dialog::{FileDialog, MessageDialog};
|
use native_dialog::{FileDialog, MessageDialog};
|
||||||
use rexiv2::Metadata;
|
use rexiv2::Metadata;
|
||||||
use rust_embed::RustEmbed;
|
use rust_embed::RustEmbed;
|
||||||
use simplelog::{ColorChoice, ConfigBuilder, LevelFilter, TermLogger, TerminalMode};
|
use simplelog::{ColorChoice, ConfigBuilder, LevelFilter, TermLogger, TerminalMode};
|
||||||
use std::{fs::File, io::BufWriter, path::PathBuf, thread::JoinHandle};
|
use std::{fs::File, io::BufWriter, path::PathBuf, thread::JoinHandle, num::NonZeroU32};
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
use warp::Filter;
|
use warp::Filter;
|
||||||
use wry::{
|
use wry::{
|
||||||
|
@ -19,6 +20,7 @@ use wry::{
|
||||||
},
|
},
|
||||||
webview::WebViewBuilder,
|
webview::WebViewBuilder,
|
||||||
};
|
};
|
||||||
|
use fast_image_resize as fr;
|
||||||
|
|
||||||
#[derive(RustEmbed)]
|
#[derive(RustEmbed)]
|
||||||
#[folder = "embed/"]
|
#[folder = "embed/"]
|
||||||
|
@ -39,15 +41,11 @@ fn main() -> Result<()> {
|
||||||
let tmp_dir = tempdir()?;
|
let tmp_dir = tempdir()?;
|
||||||
|
|
||||||
let cmd = Command::new("Simple panorama viewer")
|
let cmd = Command::new("Simple panorama viewer")
|
||||||
.arg(
|
.arg(Arg::new("filename").value_parser(clap::value_parser!(PathBuf)).help("Image path"))
|
||||||
Arg::new("filename")
|
|
||||||
.allow_invalid_utf8(true)
|
|
||||||
.help("Image path"),
|
|
||||||
)
|
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let img_path = if let Some(img_path) = cmd.value_of_os("filename") {
|
let img_path = if let Some(img_path) = cmd.get_one::<PathBuf>("filename") {
|
||||||
PathBuf::from(img_path)
|
img_path.clone()
|
||||||
} else {
|
} else {
|
||||||
let user_dirs = directories::UserDirs::new().unwrap();
|
let user_dirs = directories::UserDirs::new().unwrap();
|
||||||
let dir = if let Some(img_dir) = user_dirs.picture_dir() {
|
let dir = if let Some(img_dir) = user_dirs.picture_dir() {
|
||||||
|
@ -72,7 +70,7 @@ fn main() -> Result<()> {
|
||||||
const MAX_IMG_SIZE: u32 = 20_000_000;
|
const MAX_IMG_SIZE: u32 = 20_000_000;
|
||||||
let img_data_path = if height * width > MAX_IMG_SIZE {
|
let img_data_path = if height * width > MAX_IMG_SIZE {
|
||||||
// @todo Option pas de resize / taille en ligne de commande
|
// @todo Option pas de resize / taille en ligne de commande
|
||||||
// @todo Option pas de resize / taille dans une config
|
// @todo Option pas de resize / taille dans une config (confy)
|
||||||
// @todo Icon
|
// @todo Icon
|
||||||
let ratio = (height * width) as f64 / MAX_IMG_SIZE as f64;
|
let ratio = (height * width) as f64 / MAX_IMG_SIZE as f64;
|
||||||
let new_height = (height as f64 / ratio.sqrt()) as u32;
|
let new_height = (height as f64 / ratio.sqrt()) as u32;
|
||||||
|
@ -80,13 +78,16 @@ fn main() -> Result<()> {
|
||||||
|
|
||||||
if MessageDialog::new()
|
if MessageDialog::new()
|
||||||
.set_title("Resize")
|
.set_title("Resize")
|
||||||
.set_text(&format!("Resize the file to {} × {}", new_width, new_height))
|
.set_text(&format!(
|
||||||
|
"Resize the file to {} × {}",
|
||||||
|
new_width, new_height
|
||||||
|
))
|
||||||
.show_confirm()?
|
.show_confirm()?
|
||||||
{
|
{
|
||||||
// Resize image
|
// Resize image
|
||||||
let img = ImageReader::open(&img_path)?.decode()?;
|
let img = ImageReader::open(&img_path)?.decode()?;
|
||||||
info!("Resize image to {} × {}", new_width, new_height);
|
info!("Resize image to {} × {}", new_width, new_height);
|
||||||
let image_resized = img.resize(new_width, new_height, FilterType::Triangle);
|
let image_resized = fast_image_resize(&img, new_width, new_height)?;
|
||||||
|
|
||||||
// Save file and add metadata
|
// Save file and add metadata
|
||||||
let tmp_img_path = tmp_dir.path().join("img.jpg");
|
let tmp_img_path = tmp_dir.path().join("img.jpg");
|
||||||
|
@ -105,7 +106,7 @@ fn main() -> Result<()> {
|
||||||
};
|
};
|
||||||
let img_data = std::fs::read(&img_data_path)?;
|
let img_data = std::fs::read(&img_data_path)?;
|
||||||
tmp_dir.close()?;
|
tmp_dir.close()?;
|
||||||
let img_base_64 = base64::encode(img_data);
|
let img_base_64 = base64::engine::general_purpose::STANDARD.encode(img_data);
|
||||||
|
|
||||||
info!("Generate HTML");
|
info!("Generate HTML");
|
||||||
let html = std::str::from_utf8(Embed::get("index.html").unwrap().data.as_ref())?
|
let html = std::str::from_utf8(Embed::get("index.html").unwrap().data.as_ref())?
|
||||||
|
@ -150,3 +151,49 @@ fn run_server(html: String) -> JoinHandle<()> {
|
||||||
async_runtime.block_on(warp::serve(hello).run(([127, 0, 0, 1], 62371)));
|
async_runtime.block_on(warp::serve(hello).run(([127, 0, 0, 1], 62371)));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fast resize
|
||||||
|
pub fn fast_image_resize(
|
||||||
|
img: &DynamicImage,
|
||||||
|
max_width: u32,
|
||||||
|
max_height: u32,
|
||||||
|
) -> Result<DynamicImage> {
|
||||||
|
// Create source image
|
||||||
|
let width = NonZeroU32::new(img.width()).unwrap();
|
||||||
|
let height = NonZeroU32::new(img.height()).unwrap();
|
||||||
|
let src_image =
|
||||||
|
fr::Image::from_vec_u8(width, height, img.to_rgb8().into_raw(), fr::PixelType::U8x3)?;
|
||||||
|
let mut src_view = src_image.view();
|
||||||
|
|
||||||
|
// Create container for data of destination image
|
||||||
|
let (dst_width, dst_height) = if width > height {
|
||||||
|
(
|
||||||
|
NonZeroU32::new(max_width).unwrap(),
|
||||||
|
NonZeroU32::new((max_width * img.height()) / img.width()).unwrap(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
NonZeroU32::new((max_height * img.width()) / img.height()).unwrap(),
|
||||||
|
NonZeroU32::new(max_height).unwrap(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
src_view.set_crop_box_to_fit_dst_size(dst_width, dst_height, None);
|
||||||
|
let mut dst_image = fr::Image::new(dst_width, dst_height, src_view.pixel_type());
|
||||||
|
|
||||||
|
// Get mutable view of destination image data
|
||||||
|
let mut dst_view = dst_image.view_mut();
|
||||||
|
|
||||||
|
// Create Resizer instance and resize source image into buffer of destination image
|
||||||
|
let mut resizer = fr::Resizer::new(fr::ResizeAlg::Convolution(fr::FilterType::Lanczos3));
|
||||||
|
resizer.resize(&src_view, &mut dst_view)?;
|
||||||
|
|
||||||
|
// Create Dynamic image
|
||||||
|
let img_buffer = image::RgbImage::from_raw(
|
||||||
|
dst_image.width().get(),
|
||||||
|
dst_image.height().get(),
|
||||||
|
dst_image.into_vec(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Ok(img_buffer.into())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue