Merge pull request #372 from kerty0/main

Add image filter to cache
This commit is contained in:
Leonardo Gibrowski Faé
2024-10-27 14:40:36 -03:00
committed by GitHub
6 changed files with 86 additions and 42 deletions

6
Cargo.lock generated
View File

@@ -244,7 +244,7 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "common"
version = "0.9.5-masterV2"
version = "0.9.5-masterV3"
dependencies = [
"criterion",
"fastrand",
@@ -853,7 +853,7 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "swww"
version = "0.9.5-masterV2"
version = "0.9.5-masterV3"
dependencies = [
"assert_cmd",
"clap",
@@ -866,7 +866,7 @@ dependencies = [
[[package]]
name = "swww-daemon"
version = "0.9.5-masterV2"
version = "0.9.5-masterV3"
dependencies = [
"common",
"keyframe",

View File

@@ -5,7 +5,7 @@ members = ["client", "daemon", "common"]
default-members = ["client", "daemon"]
[workspace.package]
version = "0.9.5-masterV2"
version = "0.9.5-masterV3"
authors = ["Leonardo Gibrowski Faé <leonardo.fae44@gmail.com>"]
edition = "2021"
license-file = "LICENSE"

View File

@@ -1,6 +1,7 @@
/// Note: this file only has basic declarations and some definitions in order to be possible to
/// import it in the build script, to automate shell completion
use clap::{Parser, ValueEnum};
use std::fmt::Display;
use std::path::PathBuf;
fn from_hex(hex: &str) -> Result<[u8; 3], String> {
@@ -74,6 +75,19 @@ impl std::str::FromStr for Filter {
}
}
impl Display for Filter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let str = match self {
Self::Nearest => "Nearest",
Self::Bilinear => "Bilinear",
Self::CatmullRom => "CatmullRom",
Self::Mitchell => "Mitchell",
Self::Lanczos3 => "Lanczos3",
};
write!(f, "{}", str)
}
}
#[derive(Clone)]
pub enum TransitionType {
None,

View File

@@ -1,15 +1,16 @@
use std::{path::Path, time::Duration};
use std::{path::Path, str::FromStr, time::Duration};
use clap::Parser;
use common::cache;
use common::ipc::{self, Answer, Client, IpcSocket, RequestSend};
use common::mmap::Mmap;
use image::Pixel;
mod imgproc;
use imgproc::*;
mod cli;
use cli::{CliImage, ResizeStrategy, Swww};
use cli::{CliImage, Filter, ResizeStrategy, Swww};
fn main() -> Result<(), String> {
let swww = Swww::parse();
@@ -119,13 +120,18 @@ fn make_img_request(
for (&dim, outputs) in dims.iter().zip(outputs) {
img_req_builder.push(
ipc::ImgSend {
img: image::RgbImage::from_pixel(dim.0, dim.1, image::Rgb(*color))
.to_vec()
.into_boxed_slice(),
img: image::RgbaImage::from_pixel(
dim.0,
dim.1,
image::Rgb(*color).to_rgba(),
)
.to_vec()
.into_boxed_slice(),
path: format!("0x{:02x}{:02x}{:02x}", color[0], color[1], color[2]),
dim,
format: pixel_format,
},
Filter::Lanczos3.to_string(),
outputs,
None,
);
@@ -176,6 +182,7 @@ fn make_img_request(
None
};
let filter = img.filter.to_string();
let img = match img.resize {
ResizeStrategy::No => img_pad(&img_raw, dim, &img.fill_color)?,
ResizeStrategy::Crop => {
@@ -196,6 +203,7 @@ fn make_img_request(
dim,
format: pixel_format,
},
filter,
outputs,
animation,
);
@@ -265,32 +273,40 @@ fn restore_from_cache(requested_outputs: &[String]) -> Result<(), String> {
let (_, _, outputs) = get_format_dims_and_outputs(requested_outputs)?;
for output in outputs.iter().flatten() {
let img_path = common::cache::get_previous_image_path(output)
.map_err(|e| format!("failed to get previous image path: {e}"))?;
#[allow(deprecated)]
if let Err(e) = process_swww_args(&Swww::Img(cli::Img {
image: cli::parse_image(&img_path)?,
outputs: output.to_string(),
no_resize: false,
resize: ResizeStrategy::Crop,
fill_color: [0, 0, 0],
filter: cli::Filter::Lanczos3,
transition_type: cli::TransitionType::None,
transition_step: std::num::NonZeroU8::MAX,
transition_duration: 0.0,
transition_fps: 30,
transition_angle: 0.0,
transition_pos: cli::CliPosition {
x: cli::CliCoord::Pixel(0.0),
y: cli::CliCoord::Pixel(0.0),
},
invert_y: false,
transition_bezier: (0.0, 0.0, 0.0, 0.0),
transition_wave: (0.0, 0.0),
})) {
if let Err(e) = restore_output(output) {
eprintln!("WARNING: failed to load cache for output {output}: {e}");
}
}
Ok(())
}
fn restore_output(output: &str) -> Result<(), String> {
let (filter, img_path) = common::cache::get_previous_image_path(output)
.map_err(|e| format!("failed to get previous image path: {e}"))?;
if img_path.is_empty() {
return Err("cache file does not exist".to_string());
}
#[allow(deprecated)]
process_swww_args(&Swww::Img(cli::Img {
image: cli::parse_image(&img_path)?,
outputs: output.to_string(),
no_resize: false,
resize: ResizeStrategy::Crop,
fill_color: [0, 0, 0],
filter: Filter::from_str(&filter).unwrap_or(Filter::Lanczos3),
transition_type: cli::TransitionType::None,
transition_step: std::num::NonZeroU8::MAX,
transition_duration: 0.0,
transition_fps: 30,
transition_angle: 0.0,
transition_pos: cli::CliPosition {
x: cli::CliCoord::Pixel(0.0),
y: cli::CliCoord::Pixel(0.0),
},
invert_y: false,
transition_bezier: (0.0, 0.0, 0.0, 0.0),
transition_wave: (0.0, 0.0),
}))
}

View File

@@ -14,10 +14,10 @@ use crate::ipc::Animation;
use crate::ipc::PixelFormat;
use crate::mmap::Mmap;
pub(crate) fn store(output_name: &str, img_path: &str) -> io::Result<()> {
pub(crate) fn store(output_name: &str, img_path: &str, filter: &str) -> io::Result<()> {
let mut filepath = cache_dir()?;
filepath.push(output_name);
File::create(filepath)?.write_all(img_path.as_bytes())
File::create(filepath)?.write_all(format!("{filter}\n{img_path}").as_bytes())
}
pub(crate) fn store_animation_frames(
@@ -64,28 +64,35 @@ pub fn load_animation_frames(
Ok(None)
}
pub fn get_previous_image_path(output_name: &str) -> io::Result<String> {
pub fn get_previous_image_path(output_name: &str) -> io::Result<(String, String)> {
let mut filepath = cache_dir()?;
clean_previous_verions(&filepath);
filepath.push(output_name);
if !filepath.is_file() {
return Ok("".to_string());
return Ok(("".to_string(), "".to_string()));
}
let mut buf = Vec::with_capacity(64);
File::open(filepath)?.read_to_end(&mut buf)?;
String::from_utf8(buf).map_err(|e| {
let buf = String::from_utf8(buf).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::Other,
format!("failed to decode bytes: {e}"),
)
})
})?;
match buf.split_once("\n") {
Some(buf) => Ok((buf.0.to_string(), buf.1.to_string())),
None => Err(std::io::Error::new(
std::io::ErrorKind::Other,
"failed to read image filter",
)),
}
}
pub fn load(output_name: &str) -> io::Result<()> {
let img_path = get_previous_image_path(output_name)?;
let (filter, img_path) = get_previous_image_path(output_name)?;
if img_path.is_empty() {
return Ok(());
}
@@ -105,6 +112,7 @@ pub fn load(output_name: &str) -> io::Result<()> {
.arg("img")
.args([
&format!("--outputs={output_name}"),
&format!("--filter={filter}"),
"--transition-type=none",
&img_path,
])

View File

@@ -59,7 +59,13 @@ impl ImageRequestBuilder {
}
#[inline]
pub fn push(&mut self, img: ImgSend, outputs: &[String], animation: Option<Animation>) {
pub fn push(
&mut self,
img: ImgSend,
filter: String,
outputs: &[String],
animation: Option<Animation>,
) {
self.img_count += 1;
let ImgSend {
@@ -89,7 +95,7 @@ impl ImageRequestBuilder {
// cache the request
for output in outputs.iter() {
if let Err(e) = super::cache::store(output, path) {
if let Err(e) = super::cache::store(output, path, &filter) {
eprintln!("ERROR: failed to store cache: {e}");
}
}