#[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 { // 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 { // 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 { // 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 { file_path .extension() .and_then(|extension| extension.to_str()) .map(|extension| extension.to_lowercase()) .ok_or_else(|| "Failed to get file extension".to_string()) }