1use std::path::Path;
2use std::sync::Arc;
3
4use anyhow::{Context, Result};
5
6use crate::output;
7use crate::pipeline;
8use crate::types::{ProcessConfig, ProcessedImage};
9
10pub struct ImageConverter {
11 downscale: usize,
12 quality: u8,
13 apply_debayer: bool,
14 preview_mode: bool,
15 rgba_output: bool,
16 thread_pool: Option<Arc<rayon::ThreadPool>>,
17}
18
19impl ImageConverter {
20 pub fn new() -> Self {
21 ImageConverter {
22 downscale: 1,
23 quality: 95,
24 apply_debayer: true,
25 preview_mode: false,
26 rgba_output: false,
27 thread_pool: None,
28 }
29 }
30
31 pub fn with_downscale(mut self, factor: usize) -> Self {
32 self.downscale = factor;
33 self
34 }
35
36 pub fn with_quality(mut self, quality: u8) -> Self {
37 self.quality = quality.clamp(1, 100);
38 self
39 }
40
41 pub fn without_debayer(mut self) -> Self {
42 self.apply_debayer = false;
43 self
44 }
45
46 pub fn with_preview_mode(mut self) -> Self {
47 self.preview_mode = true;
48 self
49 }
50
51 pub fn with_rgba_output(mut self) -> Self {
53 self.rgba_output = true;
54 self
55 }
56
57 pub fn with_thread_pool(mut self, pool: Arc<rayon::ThreadPool>) -> Self {
58 self.thread_pool = Some(pool);
59 self
60 }
61
62 pub fn process<P: AsRef<Path>>(&self, input_path: P) -> Result<ProcessedImage> {
67 let config = ProcessConfig {
68 downscale_factor: self.downscale,
69 jpeg_quality: self.quality,
70 apply_debayer: self.apply_debayer,
71 preview_mode: self.preview_mode,
72 auto_stretch: true,
73 rgba_output: self.rgba_output,
74 };
75
76 let path = input_path.as_ref();
77 match &self.thread_pool {
78 Some(pool) => pool.install(|| pipeline::process_image(path, &config)),
79 None => pipeline::process_image(path, &config),
80 }
81 .context("Image processing failed")
82 }
83
84 pub fn convert<P: AsRef<Path>, Q: AsRef<Path>>(
86 &self,
87 input_path: P,
88 output_path: Q,
89 ) -> Result<()> {
90 let image = self.process(&input_path)?;
91
92 output::save_image(&image, output_path.as_ref(), self.quality)
93 .context("Image save failed")?;
94
95 Ok(())
96 }
97}
98
99impl Default for ImageConverter {
100 fn default() -> Self {
101 Self::new()
102 }
103}