mirror of
https://github.com/Vomitblood/stort.git
synced 2024-11-26 13:55:27 +08:00
added process wallpaper image tauri function
This commit is contained in:
parent
aafa0b9430
commit
69332f1655
|
@ -8,21 +8,6 @@ enum ImageType {
|
||||||
Unsupported,
|
Unsupported,
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn process_image(file_path_string: String) -> Result<String, String> {
|
|
||||||
// // convert string to path to use in rust
|
|
||||||
// let file_path = std::path::Path::new(&file_path_string);
|
|
||||||
|
|
||||||
// // get the data directory path
|
|
||||||
// let data_dir = tauri::api::path::data_dir().ok_or("Failed to get data directory")?;
|
|
||||||
// let mut destination = data_dir.clone();
|
|
||||||
// // we can hardcode the file name since
|
|
||||||
// // 1. we are only dealing with one wallpaper image at a time
|
|
||||||
// // 2. we will be converting all images to the webp format
|
|
||||||
// destination.push("wallpaper.webp");
|
|
||||||
|
|
||||||
// // determine the file format
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// determines the image type of a file that is passed in using the filepath
|
/// determines the image type of a file that is passed in using the filepath
|
||||||
fn determine_image_type(file_path: &std::path::Path) -> Result<ImageType, String> {
|
fn determine_image_type(file_path: &std::path::Path) -> Result<ImageType, String> {
|
||||||
// open the file
|
// open the file
|
||||||
|
@ -70,49 +55,58 @@ fn is_animated_webp(file_path: &std::path::Path) -> Result<bool, String> {
|
||||||
.map_err(|_| "File is not a valid WebP image".to_string())
|
.map_err(|_| "File is not a valid WebP image".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// crop static images (jpeg, png and still webp) to a maximum of 1280x800 and maintaining aspect ratio
|
fn get_file_extension(file_path: &std::path::Path) -> Result<String, String> {
|
||||||
fn crop_static_image(
|
file_path
|
||||||
file_path: &std::path::Path,
|
.extension()
|
||||||
destination: &std::path::Path,
|
.and_then(|extension| extension.to_str())
|
||||||
) -> Result<(), String> {
|
.map(|extension| extension.to_lowercase())
|
||||||
let img = image::open(file_path).map_err(|e| format!("Failed to open image: {e}"))?;
|
.ok_or_else(|| "Failed to get file extension".to_string())
|
||||||
let (width, height) = image::GenericImageView::dimensions(&img);
|
|
||||||
|
|
||||||
let resized_img = if width > 1280 || height > 800 {
|
|
||||||
img.resize(1280, 800, image::imageops::FilterType::Lanczos3)
|
|
||||||
} else {
|
|
||||||
img
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut output_file = std::fs::File::create(destination)
|
|
||||||
.map_err(|e: std::io::Error| format!("Failed to create file: {e}"))?;
|
|
||||||
resized_img
|
|
||||||
.write_to(&mut output_file, image::ImageFormat::WebP)
|
|
||||||
.map_err(|e| format!("Failed to save image as WebP: {}", e))?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// crop animated webp images
|
/// function to interface with the tauri api on the javascript side
|
||||||
fn crop_animated_webp(
|
fn process_wallpaper_image(file_path_string: String) -> Result<String, String> {
|
||||||
file_path: &std::path::Path,
|
// convert the string to a path
|
||||||
destination: &std::path::Path,
|
let file_path = std::path::Path::new(&file_path_string);
|
||||||
) -> Result<(), String> {
|
|
||||||
let mut buffer = Vec::new();
|
|
||||||
std::fs::File::open(file_path)
|
|
||||||
.and_then(|mut file| std::io::Read::read_to_end(&mut file, &mut buffer))
|
|
||||||
.map_err(|e| format!("Failed to read file: {}", e))?;
|
|
||||||
|
|
||||||
let decoder = webp::AnimDecoder::new(&buffer);
|
// determine the image type
|
||||||
let decoded = decoder
|
match determine_image_type(file_path) {
|
||||||
.decode()
|
Ok(image_type) => {
|
||||||
.map_err(|e| format!("Failed to decode WebP animation: {e}"))?;
|
// convert the image type to a string extension for printing
|
||||||
|
let extension = match image_type {
|
||||||
|
ImageType::Jpeg => "jpeg",
|
||||||
|
ImageType::Png => "png",
|
||||||
|
ImageType::Gif => "gif",
|
||||||
|
ImageType::WebP => "webp",
|
||||||
|
ImageType::AnimatedWebP => "webp",
|
||||||
|
ImageType::Unsupported => "",
|
||||||
|
};
|
||||||
|
Ok(extension.to_string())
|
||||||
|
}
|
||||||
|
Err(e) => Err(format!("Error determining image type: {e}")),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Example usage
|
// Example usage
|
||||||
let path = std::path::Path::new("/home/vomitblood/Downloads/title.keys");
|
let path = std::path::Path::new("/home/vomitblood/Downloads/background.jpg");
|
||||||
match determine_image_type(path) {
|
match determine_image_type(path) {
|
||||||
Ok(image_type) => println!("Image type: {:?}", image_type),
|
Ok(image_type) => {
|
||||||
Err(e) => println!("Error determining image type: {}", e),
|
// convert the image type to a string extension for printing
|
||||||
|
let extension = match image_type {
|
||||||
|
ImageType::Jpeg => "jpeg",
|
||||||
|
ImageType::Png => "png",
|
||||||
|
ImageType::Gif => "gif",
|
||||||
|
ImageType::WebP => "webp",
|
||||||
|
ImageType::AnimatedWebP => "webp",
|
||||||
|
ImageType::Unsupported => "",
|
||||||
|
};
|
||||||
|
println!("Image extension: {extension}");
|
||||||
|
}
|
||||||
|
Err(e) => println!("Error determining image type: {e}"),
|
||||||
|
}
|
||||||
|
|
||||||
|
match get_file_extension(path) {
|
||||||
|
Ok(extension) => println!("File extension: {extension}"),
|
||||||
|
Err(e) => println!("Error getting file extension: {e}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
src-tauri/src/lib.rs
Normal file
1
src-tauri/src/lib.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod wallpaper;
|
|
@ -1,8 +1,11 @@
|
||||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
|
|
||||||
|
use app::wallpaper;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
|
.invoke_handler(tauri::generate_handler![wallpaper::process_wallpaper_image])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
}
|
}
|
||||||
|
|
86
src-tauri/src/wallpaper.rs
Normal file
86
src-tauri/src/wallpaper.rs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
enum ImageType {
|
||||||
|
Jpeg,
|
||||||
|
Png,
|
||||||
|
Gif,
|
||||||
|
WebP,
|
||||||
|
AnimatedWebP,
|
||||||
|
Unsupported,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// function to interface with the tauri api on the javascript side
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn process_wallpaper_image(file_path_string: String) -> Result<String, String> {
|
||||||
|
// convert the string to a path
|
||||||
|
let file_path = std::path::Path::new(&file_path_string);
|
||||||
|
|
||||||
|
// determine the image type
|
||||||
|
match determine_image_type(file_path) {
|
||||||
|
Ok(image_type) => match image_type {
|
||||||
|
ImageType::Jpeg => Ok("jpeg".to_string()),
|
||||||
|
ImageType::Png => Ok("png".to_string()),
|
||||||
|
ImageType::Gif => Ok("gif".to_string()),
|
||||||
|
ImageType::WebP => Ok("webp".to_string()),
|
||||||
|
ImageType::AnimatedWebP => Ok("webp".to_string()),
|
||||||
|
ImageType::Unsupported => {
|
||||||
|
Err("Unsupported image type (accepts webp, jpg, jpeg, png, gif)".to_string())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => Err(format!("Error determining image type: {e}")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// determines the image type of a file that is passed in using the filepath
|
||||||
|
fn determine_image_type(file_path: &std::path::Path) -> Result<ImageType, String> {
|
||||||
|
// open the file
|
||||||
|
let mut file =
|
||||||
|
std::fs::File::open(file_path).map_err(|e| format!("Failed to open file: {e}"))?;
|
||||||
|
|
||||||
|
// read the first few bytes to determine the format
|
||||||
|
let mut buffer = [0; 12];
|
||||||
|
std::io::Read::read_exact(&mut file, &mut buffer)
|
||||||
|
.map_err(|e| format!("Failed to read file: {e}"))?;
|
||||||
|
|
||||||
|
// with hopes and prayers, try to guess the format and pray that it is correct haha
|
||||||
|
match image::guess_format(&buffer) {
|
||||||
|
Ok(image::ImageFormat::Jpeg) => Ok(ImageType::Jpeg),
|
||||||
|
Ok(image::ImageFormat::Png) => Ok(ImageType::Png),
|
||||||
|
Ok(image::ImageFormat::Gif) => Ok(ImageType::Gif),
|
||||||
|
Ok(image::ImageFormat::WebP) => {
|
||||||
|
// additional check for webp
|
||||||
|
is_animated_webp(file_path).map(|animated| {
|
||||||
|
if animated {
|
||||||
|
ImageType::AnimatedWebP
|
||||||
|
} else {
|
||||||
|
ImageType::WebP
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => Ok(ImageType::Unsupported),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// check if the file is a valid webp image and if it is animated
|
||||||
|
/// returns `Ok(true)` if it is animated, `Ok(false)` if it is not
|
||||||
|
/// and errors out if the file cannot be read or is not a webp
|
||||||
|
fn is_animated_webp(file_path: &std::path::Path) -> Result<bool, String> {
|
||||||
|
// open the file and read its contents into a buffer
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
std::fs::File::open(file_path)
|
||||||
|
.and_then(|mut file| std::io::Read::read_to_end(&mut file, &mut buffer))
|
||||||
|
.map_err(|e| format!("Failed to read file: {}", e))?;
|
||||||
|
|
||||||
|
// use the webp crate to decode the image and check for animation
|
||||||
|
webp::AnimDecoder::new(&buffer)
|
||||||
|
.decode()
|
||||||
|
.map(|anim| anim.has_animation())
|
||||||
|
.map_err(|_| "File is not a valid WebP image".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_file_extension(file_path: &std::path::Path) -> Result<String, String> {
|
||||||
|
file_path
|
||||||
|
.extension()
|
||||||
|
.and_then(|extension| extension.to_str())
|
||||||
|
.map(|extension| extension.to_lowercase())
|
||||||
|
.ok_or_else(|| "Failed to get file extension".to_string())
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import { useState } from "react";
|
||||||
import { SettingsItem } from "../components/HeaderBar/Settings/SettingsItem";
|
import { SettingsItem } from "../components/HeaderBar/Settings/SettingsItem";
|
||||||
import { useSettings } from "../contexts/SettingsContext";
|
import { useSettings } from "../contexts/SettingsContext";
|
||||||
import { testing } from "../lib/testing";
|
import { testing } from "../lib/testing";
|
||||||
|
import { invoke } from "@tauri-apps/api/tauri";
|
||||||
|
|
||||||
export default function Testing() {
|
export default function Testing() {
|
||||||
// contexts
|
// contexts
|
||||||
|
@ -24,28 +25,42 @@ export default function Testing() {
|
||||||
>
|
>
|
||||||
<BugReport />
|
<BugReport />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<Button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
resetSettings();
|
resetSettings();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
reset settings
|
reset settings
|
||||||
</Button>
|
</button>
|
||||||
<Button>update settings</Button>
|
<button>update settings</button>
|
||||||
<Button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log(settings);
|
console.log(settings);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
log settings
|
log settings
|
||||||
</Button>
|
</button>
|
||||||
<Button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log(testing());
|
console.log(testing());
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
testing
|
testing
|
||||||
</Button>
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
const bruh = await invoke("process_wallpaper_image", {
|
||||||
|
filePathString: "/home/vomitblood/Downloads/9fd62bc7_2024-08-07_7.csv",
|
||||||
|
});
|
||||||
|
console.log(bruh);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("deec nuts", error);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
invoke tauri shit
|
||||||
|
</button>
|
||||||
<Typography>{text}</Typography>
|
<Typography>{text}</Typography>
|
||||||
<SettingsItem
|
<SettingsItem
|
||||||
defaultText="#8ab4f8"
|
defaultText="#8ab4f8"
|
||||||
|
|
Loading…
Reference in a new issue