use serde::{Deserialize, Serialize}; use crate::operations::*; use crate::pipeline::ProcessingJob; use crate::types::*; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Preset { pub name: String, pub description: String, pub icon: String, pub is_custom: bool, pub resize: Option, pub rotation: Option, pub flip: Option, pub convert: Option, pub compress: Option, pub metadata: Option, pub watermark: Option, pub rename: Option, } impl Preset { pub fn to_job( &self, input_dir: impl Into, output_dir: impl Into, ) -> ProcessingJob { ProcessingJob { input_dir: input_dir.into(), output_dir: output_dir.into(), sources: Vec::new(), resize: self.resize.clone(), resize_algorithm: crate::operations::ResizeAlgorithm::default(), rotation: self.rotation, flip: self.flip, adjustments: None, convert: self.convert.clone(), compress: self.compress.clone(), metadata: self.metadata.clone(), watermark: self.watermark.clone(), rename: self.rename.clone(), overwrite_behavior: crate::operations::OverwriteBehavior::default(), preserve_directory_structure: false, progressive_jpeg: false, avif_speed: 6, } } pub fn all_builtins() -> Vec { vec![ Self::builtin_blog_photos(), Self::builtin_social_media(), Self::builtin_web_optimization(), Self::builtin_email_friendly(), Self::builtin_privacy_clean(), Self::builtin_photographer_export(), Self::builtin_archive_compress(), Self::builtin_fediverse_ready(), ] } pub fn builtin_blog_photos() -> Preset { Preset { name: "Blog Photos".into(), description: "Resize 1200px wide, JPEG quality High, strip all metadata".into(), icon: "image-x-generic-symbolic".into(), is_custom: false, resize: Some(ResizeConfig::ByWidth(1200)), rotation: None, flip: None, convert: None, compress: Some(CompressConfig::Preset(QualityPreset::High)), metadata: Some(MetadataConfig::StripAll), watermark: None, rename: None, } } pub fn builtin_social_media() -> Preset { Preset { name: "Social Media".into(), description: "Resize to fit 1080x1080, compress Medium, strip metadata".into(), icon: "system-users-symbolic".into(), is_custom: false, resize: Some(ResizeConfig::FitInBox { max: Dimensions { width: 1080, height: 1080, }, allow_upscale: false, }), rotation: None, flip: None, convert: None, compress: Some(CompressConfig::Preset(QualityPreset::Medium)), metadata: Some(MetadataConfig::StripAll), watermark: None, rename: None, } } pub fn builtin_web_optimization() -> Preset { Preset { name: "Web Optimization".into(), description: "Convert to WebP, compress High, sequential rename".into(), icon: "web-browser-symbolic".into(), is_custom: false, resize: None, rotation: None, flip: None, convert: Some(ConvertConfig::SingleFormat(ImageFormat::WebP)), compress: Some(CompressConfig::Preset(QualityPreset::High)), metadata: Some(MetadataConfig::StripAll), watermark: None, rename: Some(RenameConfig { prefix: String::new(), suffix: String::new(), counter_start: 1, counter_padding: 3, template: None, }), } } pub fn builtin_email_friendly() -> Preset { Preset { name: "Email Friendly".into(), description: "Resize 800px wide, JPEG quality Medium".into(), icon: "mail-unread-symbolic".into(), is_custom: false, resize: Some(ResizeConfig::ByWidth(800)), rotation: None, flip: None, convert: None, compress: Some(CompressConfig::Preset(QualityPreset::Medium)), metadata: Some(MetadataConfig::StripAll), watermark: None, rename: None, } } pub fn builtin_privacy_clean() -> Preset { Preset { name: "Privacy Clean".into(), description: "Strip all metadata, no other changes".into(), icon: "security-high-symbolic".into(), is_custom: false, resize: None, rotation: None, flip: None, convert: None, compress: None, metadata: Some(MetadataConfig::StripAll), watermark: None, rename: None, } } pub fn builtin_photographer_export() -> Preset { Preset { name: "Photographer Export".into(), description: "Resize 2048px, compress High, privacy metadata, rename by date".into(), icon: "camera-photo-symbolic".into(), is_custom: false, resize: Some(ResizeConfig::ByWidth(2048)), rotation: None, flip: None, convert: None, compress: Some(CompressConfig::Preset(QualityPreset::High)), metadata: Some(MetadataConfig::Privacy), watermark: None, rename: Some(RenameConfig { prefix: String::new(), suffix: String::new(), counter_start: 1, counter_padding: 4, template: Some("{exif_date}_{name}_{counter:4}".into()), }), } } pub fn builtin_archive_compress() -> Preset { Preset { name: "Archive Compress".into(), description: "Lossless compression, preserve metadata".into(), icon: "folder-symbolic".into(), is_custom: false, resize: None, rotation: None, flip: None, convert: None, compress: Some(CompressConfig::Preset(QualityPreset::Maximum)), metadata: Some(MetadataConfig::KeepAll), watermark: None, rename: None, } } pub fn builtin_fediverse_ready() -> Preset { Preset { name: "Fediverse Ready".into(), description: "Resize 1920x1080, convert to WebP, compress High, strip metadata".into(), icon: "network-server-symbolic".into(), is_custom: false, resize: Some(ResizeConfig::FitInBox { max: Dimensions { width: 1920, height: 1080, }, allow_upscale: false, }), rotation: None, flip: None, convert: Some(ConvertConfig::SingleFormat(ImageFormat::WebP)), compress: Some(CompressConfig::Preset(QualityPreset::High)), metadata: Some(MetadataConfig::StripAll), watermark: None, rename: None, } } }