1pub mod ocr;
2pub mod face;
3
4use anyhow::{Context, Result};
5use std::fs;
6use std::path::Path;
7use tracing::{debug, info};
8
9use ocr::detection::detect_text_with_api;
10use ocr::masking::mask_text;
11use face::detection::detect_faces_with_api;
12use face::masking::mask_faces;
13
14pub fn process_image(
32 input_path: &Path,
33 output_dir: &Path,
34 mask_texts: Option<&str>,
35 mask_faces_flag: bool
36) -> Result<()> {
37 info!("Image processing started");
38 info!("Reading input image: {:?}", input_path);
39 let mut img = image::open(input_path).context("Failed to open input image")?;
40
41 let file_name = input_path
42 .file_name()
43 .context("Invalid input filename")?
44 .to_str()
45 .context("Non-UTF8 filename")?;
46
47 let output_path = output_dir.join(format!("masked_{}", file_name));
48
49 if !output_dir.exists() {
51 debug!("Creating output directory: {:?}", output_dir);
52 fs::create_dir_all(output_dir).context("Failed to create output directory")?;
53 }
54
55 let additional_masks = if let Some(texts) = mask_texts {
57 texts
58 .split(',')
59 .map(|text| text.trim().to_string())
60 .collect::<Vec<_>>()
61 } else {
62 Vec::new()
63 };
64
65 let annotations = detect_text_with_api(input_path).context("Failed to detect text in image")?;
66
67 if annotations.is_empty() {
68 debug!("No text detected in the image");
69 } else {
70 debug!("Detected {} text annotations", annotations.len());
71 mask_text(&mut img, &annotations, &additional_masks).context("Failed to mask text")?;
72 }
73
74 if mask_faces_flag {
76 info!("Face detection enabled, detecting faces...");
77 match detect_faces_with_api(input_path) {
78 Ok(face_annotations) => {
79 if face_annotations.is_empty() {
80 info!("No faces detected in the image");
81 } else {
82 info!("Detected {} faces in the image", face_annotations.len());
83 mask_faces(&mut img, &face_annotations).context("Failed to mask faces")?;
84 }
85 },
86 Err(e) => {
87 debug!("Face detection failed: {}", e);
88 info!("Skipping face masking due to detection error");
89 }
90 }
91 }
92
93 img.save(&output_path)
94 .context("Failed to save output image")?;
95
96 info!("Saved processed image to: {:?}", output_path);
97 Ok(())
98}