Compare commits

...

7 Commits

2 changed files with 30 additions and 14 deletions

View File

@ -18,4 +18,3 @@ path = "src/main.rs"
opt-level = "z" # Optimize for size opt-level = "z" # Optimize for size
lto = true # Enable link-time optimization lto = true # Enable link-time optimization
codegen-units = 1 codegen-units = 1
panic = "abort"

View File

@ -71,6 +71,28 @@ fn libraw_error_string(code: c_int) -> &'static str {
} }
} }
/// RAII guard for libraw memory cleanup.
/// Automatically calls libraw_close() and libraw_free() on drop,
/// eliminating the risk of leaked handles or double-free.
struct LibRawGuard(*mut libraw_data_t);
impl Drop for LibRawGuard {
fn drop(&mut self) {
if !self.0.is_null() {
unsafe {
libraw_close(self.0);
libraw_free(self.0);
}
}
}
}
impl LibRawGuard {
fn ptr(&self) -> *mut libraw_data_t {
self.0
}
}
/// Photo Editor - A Rust-based photo editor with RAW image processing capabilities using libraw /// Photo Editor - A Rust-based photo editor with RAW image processing capabilities using libraw
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
@ -226,12 +248,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("\n[INFO] Attempting RAW image processing with libraw integration..."); println!("\n[INFO] Attempting RAW image processing with libraw integration...");
// Initialize libraw // Initialize libraw with RAII guard for automatic cleanup
let lr = unsafe { libraw_init(LIBRAW_OPTIONS_NONE) }; let lr_raw = unsafe { libraw_init(LIBRAW_OPTIONS_NONE) };
if lr.is_null() { if lr_raw.is_null() {
eprintln!("Error: Failed to initialize libraw"); eprintln!("Error: Failed to initialize libraw");
return Err("Failed to initialize libraw".into()); return Err("Failed to initialize libraw".into());
} }
let lr_guard = LibRawGuard(lr_raw);
let lr = lr_guard.ptr();
// Open the RAW file // Open the RAW file
let input_cstr = CString::new(input_path.to_string_lossy().as_bytes()) let input_cstr = CString::new(input_path.to_string_lossy().as_bytes())
@ -240,7 +264,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
if ret != LIBRAW_SUCCESS { if ret != LIBRAW_SUCCESS {
eprintln!("Error: Failed to open file: {}", libraw_error_string(ret)); eprintln!("Error: Failed to open file: {}", libraw_error_string(ret));
unsafe { libraw_close(lr) };
return Err("Failed to open file".into()); return Err("Failed to open file".into());
} }
@ -250,7 +273,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let ret = unsafe { libraw_unpack(lr) }; let ret = unsafe { libraw_unpack(lr) };
if ret != LIBRAW_SUCCESS { if ret != LIBRAW_SUCCESS {
eprintln!("Error: Failed to unpack RAW data: {}", libraw_error_string(ret)); eprintln!("Error: Failed to unpack RAW data: {}", libraw_error_string(ret));
unsafe { libraw_close(lr) };
return Err("Failed to unpack RAW data".into()); return Err("Failed to unpack RAW data".into());
} }
@ -265,7 +287,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let ret = unsafe { libraw_dcraw_process(lr) }; let ret = unsafe { libraw_dcraw_process(lr) };
if ret != LIBRAW_SUCCESS { if ret != LIBRAW_SUCCESS {
eprintln!("Error: Failed to process image: {}", libraw_error_string(ret)); eprintln!("Error: Failed to process image: {}", libraw_error_string(ret));
unsafe { libraw_close(lr) };
return Err("Failed to process image".into()); return Err("Failed to process image".into());
} }
@ -317,17 +338,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
if ret != LIBRAW_SUCCESS { if ret != LIBRAW_SUCCESS {
eprintln!("Error: Failed to write output file: {}", libraw_error_string(ret)); eprintln!("Error: Failed to write output file: {}", libraw_error_string(ret));
unsafe { libraw_close(lr) };
return Err("Failed to write output file".into()); return Err("Failed to write output file".into());
} }
println!("[INFO] Processed image written to disk"); println!("[INFO] Processed image written to disk");
// Clean up
unsafe {
libraw_close(lr);
}
println!("\n[SUCCESS] Photo editing completed successfully with libraw integration!"); println!("\n[SUCCESS] Photo editing completed successfully with libraw integration!");
println!( println!(
"[NOTICE] The edited image has been saved as: {}", "[NOTICE] The edited image has been saved as: {}",
@ -347,7 +362,9 @@ fn apply_image_parameters(lr: *mut libraw_data_t, args: &Args) {
// Apply exposure adjustment // Apply exposure adjustment
if args.exposure != 0.0 && !lr.is_null() { if args.exposure != 0.0 && !lr.is_null() {
libraw_set_bright(lr, args.exposure); // Convert EV stops to brightness multiplier: EV 1.0 → 2x, EV -1.0 → 0.5x
let multiplier = 2.0f32.powf(args.exposure);
libraw_set_bright(lr, multiplier);
} }
// Apply contrast (map to brightness multiplier for tonal range) // Apply contrast (map to brightness multiplier for tonal range)