Files
pixstrip/pixstrip-core/src/pipeline.rs

110 lines
3.4 KiB
Rust

use std::path::{Path, PathBuf};
use serde::{Deserialize, Serialize};
use crate::operations::*;
use crate::types::{ImageFormat, ImageSource};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProcessingJob {
pub input_dir: PathBuf,
pub output_dir: PathBuf,
#[serde(skip)]
pub sources: Vec<ImageSource>,
pub resize: Option<ResizeConfig>,
pub resize_algorithm: ResizeAlgorithm,
pub rotation: Option<Rotation>,
pub flip: Option<Flip>,
pub adjustments: Option<AdjustmentsConfig>,
pub convert: Option<ConvertConfig>,
pub compress: Option<CompressConfig>,
pub metadata: Option<MetadataConfig>,
pub watermark: Option<WatermarkConfig>,
pub rename: Option<RenameConfig>,
pub overwrite_behavior: OverwriteBehavior,
pub preserve_directory_structure: bool,
pub progressive_jpeg: bool,
pub avif_speed: u8,
pub output_dpi: u32,
}
impl ProcessingJob {
pub fn new(input_dir: impl AsRef<Path>, output_dir: impl AsRef<Path>) -> Self {
Self {
input_dir: input_dir.as_ref().to_path_buf(),
output_dir: output_dir.as_ref().to_path_buf(),
sources: Vec::new(),
resize: None,
resize_algorithm: ResizeAlgorithm::default(),
rotation: None,
flip: None,
adjustments: None,
convert: None,
compress: None,
metadata: None,
watermark: None,
rename: None,
overwrite_behavior: OverwriteBehavior::default(),
preserve_directory_structure: false,
progressive_jpeg: false,
avif_speed: 6,
output_dpi: 72,
}
}
pub fn add_source(&mut self, path: impl AsRef<Path>) {
self.sources.push(ImageSource::from_path(path));
}
pub fn operation_count(&self) -> usize {
let mut count = 0;
if self.resize.is_some() { count += 1; }
if self.rotation.is_some() { count += 1; }
if self.flip.is_some() { count += 1; }
if self.adjustments.as_ref().is_some_and(|a| !a.is_noop()) { count += 1; }
if self.convert.is_some() { count += 1; }
if self.compress.is_some() { count += 1; }
if self.metadata.is_some() { count += 1; }
if self.watermark.is_some() { count += 1; }
if self.rename.is_some() { count += 1; }
count
}
pub fn output_path_for(
&self,
source: &ImageSource,
output_format: Option<ImageFormat>,
) -> PathBuf {
let stem = source
.path
.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("output");
let ext = output_format
.map(|f| f.extension())
.or_else(|| {
source
.path
.extension()
.and_then(|e| e.to_str())
})
.unwrap_or("bin");
let filename = format!("{}.{}", stem, ext);
if self.preserve_directory_structure {
// Maintain relative path from input_dir
if let Ok(rel) = source.path.strip_prefix(&self.input_dir) {
if let Some(parent) = rel.parent() {
if parent.components().count() > 0 {
return self.output_dir.join(parent).join(filename);
}
}
}
}
self.output_dir.join(filename)
}
}