1use std::path::Path;
2
3use anyhow::{Context, Result};
4
5use crate::output;
6use crate::pipeline;
7use crate::types::{ProcessConfig, ProcessedImage};
8
9pub struct ImageConverter {
10 downscale: usize,
11 quality: u8,
12 apply_debayer: bool,
13 preview_mode: bool,
14}
15
16impl ImageConverter {
17 pub fn new() -> Self {
18 ImageConverter {
19 downscale: 1,
20 quality: 95,
21 apply_debayer: true,
22 preview_mode: false,
23 }
24 }
25
26 pub fn with_downscale(mut self, factor: usize) -> Self {
27 self.downscale = factor;
28 self
29 }
30
31 pub fn with_quality(mut self, quality: u8) -> Self {
32 self.quality = quality.clamp(1, 100);
33 self
34 }
35
36 pub fn without_debayer(mut self) -> Self {
37 self.apply_debayer = false;
38 self
39 }
40
41 pub fn with_preview_mode(mut self) -> Self {
42 self.preview_mode = true;
43 self
44 }
45
46 pub fn process<P: AsRef<Path>>(&self, input_path: P) -> Result<ProcessedImage> {
51 let config = ProcessConfig {
52 downscale_factor: self.downscale,
53 jpeg_quality: self.quality,
54 apply_debayer: self.apply_debayer,
55 preview_mode: self.preview_mode,
56 auto_stretch: true,
57 };
58
59 pipeline::process_image(input_path.as_ref(), &config)
60 .context("Image processing failed")
61 }
62
63 pub fn convert<P: AsRef<Path>, Q: AsRef<Path>>(
65 &self,
66 input_path: P,
67 output_path: Q,
68 ) -> Result<()> {
69 let image = self.process(&input_path)?;
70
71 output::save_image(&image, output_path.as_ref(), self.quality)
72 .context("Image save failed")?;
73
74 Ok(())
75 }
76}
77
78impl Default for ImageConverter {
79 fn default() -> Self {
80 Self::new()
81 }
82}