Skip to content

Commit 02347b7

Browse files
committed
chore: update .gitignore and enhance code safety with clippy lints
- Added .claude/settings.local.json to .gitignore to prevent local configuration files from being tracked. - Introduced clippy lints to suppress warnings for functions with too many arguments in invers-cli and invers-core. - Improved code formatting and readability in various files, including adjustments to arithmetic operations and test data initialization.
1 parent 43313e1 commit 02347b7

10 files changed

Lines changed: 53 additions & 50 deletions

File tree

.claude/settings.local.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
"Bash(curl:*)",
3535
"Bash(./scripts/update-formula.sh:*)",
3636
"Bash(tar:*)",
37-
"Bash(cargo check:*)"
37+
"Bash(cargo check:*)",
38+
"Bash(cargo clippy:*)"
3839
],
3940
"deny": [],
4041
"ask": []

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,4 @@ target/
3131
OPTIMIZATION_SUMMARY.md
3232

3333
docs/
34+
.claude/settings.local.json

crates/invers-cli/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ pub fn parse_inversion_mode(
163163
///
164164
/// This function centralizes the logic for building ConvertOptions with all
165165
/// pipeline defaults, making it reusable across CLI and GUI applications.
166+
#[allow(clippy::too_many_arguments)]
166167
pub fn build_convert_options(
167168
input: PathBuf,
168169
output_dir: PathBuf,
@@ -191,6 +192,7 @@ pub fn build_convert_options(
191192
}
192193

193194
/// Build a ConvertOptions struct with explicit inversion mode override
195+
#[allow(clippy::too_many_arguments)]
194196
pub fn build_convert_options_with_inversion(
195197
input: PathBuf,
196198
output_dir: PathBuf,
@@ -225,6 +227,7 @@ pub fn build_convert_options_with_inversion(
225227
}
226228

227229
/// Build a ConvertOptions struct with all options
230+
#[allow(clippy::too_many_arguments)]
228231
pub fn build_convert_options_full(
229232
input: PathBuf,
230233
output_dir: PathBuf,
@@ -266,6 +269,7 @@ pub fn build_convert_options_full(
266269
}
267270

268271
/// Build a ConvertOptions struct with all options including GPU control
272+
#[allow(clippy::too_many_arguments)]
269273
pub fn build_convert_options_full_with_gpu(
270274
input: PathBuf,
271275
output_dir: PathBuf,

crates/invers-cli/src/main.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ fn main() {
428428
}
429429
}
430430

431+
#[allow(clippy::too_many_arguments)]
431432
fn cmd_convert(
432433
input: PathBuf,
433434
out: Option<PathBuf>,
@@ -824,7 +825,7 @@ fn cmd_analyze(
824825
// Parse base estimation method
825826
let method = match base_method.to_lowercase().as_str() {
826827
"border" => invers_core::models::BaseEstimationMethod::Border,
827-
"regions" | _ => invers_core::models::BaseEstimationMethod::Regions,
828+
_ => invers_core::models::BaseEstimationMethod::Regions,
828829
};
829830

830831
// Estimate base
@@ -927,6 +928,7 @@ fn cmd_analyze(
927928
Ok(())
928929
}
929930

931+
#[allow(clippy::too_many_arguments)]
930932
fn cmd_batch(
931933
inputs: Vec<PathBuf>,
932934
base_from: Option<PathBuf>,
@@ -1299,8 +1301,8 @@ fn cmd_init(force: bool) -> Result<(), String> {
12991301
}
13001302

13011303
fn copy_dir_contents(
1302-
src: &PathBuf,
1303-
dst: &PathBuf,
1304+
src: &std::path::Path,
1305+
dst: &std::path::Path,
13041306
force: bool,
13051307
indent: &str,
13061308
) -> Result<(), String> {
@@ -1335,6 +1337,7 @@ fn copy_dir_contents(
13351337
Ok(())
13361338
}
13371339

1340+
#[allow(clippy::too_many_arguments)]
13381341
fn cmd_diagnose(
13391342
original: PathBuf,
13401343
third_party: PathBuf,
@@ -1459,6 +1462,7 @@ fn cmd_diagnose(
14591462
Ok(())
14601463
}
14611464

1465+
#[allow(clippy::too_many_arguments)]
14621466
fn cmd_test_params(
14631467
original: PathBuf,
14641468
reference: PathBuf,

crates/invers-core/src/auto_adjust.rs

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,7 +1238,7 @@ fn auto_exposure_impl(
12381238
}
12391239
} else {
12401240
for value in data.iter_mut() {
1241-
*value = *value * gain;
1241+
*value *= gain;
12421242
}
12431243
}
12441244

@@ -1329,15 +1329,8 @@ mod tests {
13291329
fn test_otsu_threshold_bimodal() {
13301330
// Create truly bimodal distribution with clear separation
13311331
// All low values exactly at 0.2, all high values exactly at 0.8
1332-
let mut data = Vec::new();
1333-
// Low cluster: 500 samples at 0.2
1334-
for _ in 0..500 {
1335-
data.push(0.2);
1336-
}
1337-
// High cluster: 500 samples at 0.8
1338-
for _ in 0..500 {
1339-
data.push(0.8);
1340-
}
1332+
let mut data = vec![0.2; 500]; // Low cluster: 500 samples at 0.2
1333+
data.extend(vec![0.8; 500]); // High cluster: 500 samples at 0.8
13411334

13421335
let result = otsu_threshold(&data);
13431336

@@ -1364,19 +1357,9 @@ mod tests {
13641357
#[test]
13651358
fn test_measure_dark_mid_light() {
13661359
// Create data with known distribution
1367-
let mut data = Vec::new();
1368-
// 25% dark (0.0-0.25)
1369-
for _ in 0..25 {
1370-
data.push(0.1);
1371-
}
1372-
// 50% mid (0.25-0.75)
1373-
for _ in 0..50 {
1374-
data.push(0.5);
1375-
}
1376-
// 25% light (0.75-1.0)
1377-
for _ in 0..25 {
1378-
data.push(0.9);
1379-
}
1360+
let mut data = vec![0.1; 25]; // 25% dark (0.0-0.25)
1361+
data.extend(vec![0.5; 50]); // 50% mid (0.25-0.75)
1362+
data.extend(vec![0.9; 25]); // 25% light (0.75-1.0)
13801363

13811364
let (dark, mid, light) = measure_dark_mid_light(&data);
13821365

crates/invers-core/src/color.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,13 @@ const D65_Z: f32 = 1.08883;
229229
const SRGB_TO_XYZ: [[f32; 3]; 3] = [
230230
[0.4124564, 0.3575761, 0.1804375],
231231
[0.2126729, 0.7151522, 0.0721750],
232-
[0.0193339, 0.1191920, 0.9503041],
232+
[0.0193339, 0.119_192, 0.9503041],
233233
];
234234

235235
/// XYZ to sRGB matrix (D65)
236236
const XYZ_TO_SRGB: [[f32; 3]; 3] = [
237237
[3.2404542, -1.5371385, -0.4985314],
238-
[-0.9692660, 1.8760108, 0.0415560],
238+
[-0.969_266, 1.8760108, 0.0415560],
239239
[0.0556434, -0.2040259, 1.0572252],
240240
];
241241

crates/invers-core/src/gpu/context.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,15 @@ impl GpuContext {
154154

155155
// Request device with required features and higher buffer limits for large images
156156
// Large scans (e.g., 4000x6000 @ 48-bit) can exceed 200MB
157-
let mut limits = wgpu::Limits::default();
158-
// Request max storage buffer size from adapter (for image data)
159-
limits.max_storage_buffer_binding_size = adapter_limits.max_storage_buffer_binding_size;
160-
// Also increase uniform buffer size if needed
161-
limits.max_uniform_buffer_binding_size = adapter_limits.max_uniform_buffer_binding_size;
162-
// Increase buffer size limit
163-
limits.max_buffer_size = adapter_limits.max_buffer_size;
157+
let limits = wgpu::Limits {
158+
// Request max storage buffer size from adapter (for image data)
159+
max_storage_buffer_binding_size: adapter_limits.max_storage_buffer_binding_size,
160+
// Also increase uniform buffer size if needed
161+
max_uniform_buffer_binding_size: adapter_limits.max_uniform_buffer_binding_size,
162+
// Increase buffer size limit
163+
max_buffer_size: adapter_limits.max_buffer_size,
164+
..Default::default()
165+
};
164166

165167
let (device, queue) = adapter
166168
.request_device(

crates/invers-core/src/gpu/pipeline.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ fn clear_histogram(ctx: &GpuContext, histogram: &GpuHistogram) -> Result<(), Gpu
401401
pass.set_pipeline(&ctx.pipelines.histogram_clear);
402402
pass.set_bind_group(0, &bind_group, &[]);
403403

404-
let workgroups = (NUM_HISTOGRAM_BUCKETS as u32 + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE;
404+
let workgroups = (NUM_HISTOGRAM_BUCKETS as u32).div_ceil(WORKGROUP_SIZE);
405405
pass.dispatch_workgroups(workgroups, 1, 1);
406406
}
407407

@@ -501,14 +501,14 @@ fn accumulate_histogram(
501501
pass.set_bind_group(0, &bind_group, &[]);
502502

503503
let pixel_count = image.pixel_count();
504-
let total_workgroups = (pixel_count + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE;
504+
let total_workgroups = pixel_count.div_ceil(WORKGROUP_SIZE);
505505

506506
// Use 2D dispatch for large images
507507
let (workgroups_x, workgroups_y) = if total_workgroups <= MAX_WORKGROUPS_PER_DIM {
508508
(total_workgroups, 1)
509509
} else {
510510
let side = ((total_workgroups as f64).sqrt().ceil() as u32).min(MAX_WORKGROUPS_PER_DIM);
511-
let other = (total_workgroups + side - 1) / side;
511+
let other = total_workgroups.div_ceil(side);
512512
(side, other.min(MAX_WORKGROUPS_PER_DIM))
513513
};
514514
pass.dispatch_workgroups(workgroups_x, workgroups_y, 1);
@@ -784,6 +784,7 @@ fn clamp_working_range(
784784
const MAX_WORKGROUPS_PER_DIM: u32 = 65535;
785785

786786
/// Maximum pixels per single dispatch (65535 workgroups * 256 threads)
787+
#[allow(dead_code)]
787788
const MAX_PIXELS_PER_DISPATCH: u32 = MAX_WORKGROUPS_PER_DIM * WORKGROUP_SIZE;
788789

789790
/// Generic compute dispatch for storage + uniform pattern
@@ -838,7 +839,7 @@ fn dispatch_compute(
838839
],
839840
});
840841

841-
let total_workgroups = (pixel_count + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE;
842+
let total_workgroups = pixel_count.div_ceil(WORKGROUP_SIZE);
842843

843844
// If within limits, do a single dispatch
844845
if total_workgroups <= MAX_WORKGROUPS_PER_DIM {
@@ -865,7 +866,7 @@ fn dispatch_compute(
865866
// This allows up to 65535 * 65535 workgroups = ~4 billion workgroups
866867
// Calculate grid dimensions: try to make it roughly square for efficiency
867868
let side = ((total_workgroups as f64).sqrt().ceil() as u32).min(MAX_WORKGROUPS_PER_DIM);
868-
let workgroups_y = (total_workgroups + side - 1) / side;
869+
let workgroups_y = total_workgroups.div_ceil(side);
869870

870871
if workgroups_y > MAX_WORKGROUPS_PER_DIM {
871872
return Err(GpuError::Other(format!(
@@ -902,7 +903,7 @@ fn dispatch_compute(
902903
/// CPU-side base estimation (statistical analysis)
903904
fn estimate_base_cpu(decoded: &DecodedImage, _options: &ConvertOptions) -> BaseEstimation {
904905
// Delegate to the existing CPU implementation
905-
crate::pipeline::estimate_base(decoded, None, None, None).unwrap_or_else(|_| BaseEstimation {
906+
crate::pipeline::estimate_base(decoded, None, None, None).unwrap_or(BaseEstimation {
906907
roi: None,
907908
medians: [0.5, 0.5, 0.5],
908909
noise_stats: None,
@@ -978,10 +979,10 @@ fn compute_auto_color_gains(
978979
let mut sum: f64 = 0.0;
979980
let mut count: u64 = 0;
980981

981-
for i in low_idx..=high_idx.min(buckets - 1) {
982+
for (i, &bin_count) in hist.iter().enumerate().take(high_idx.min(buckets - 1) + 1).skip(low_idx) {
982983
let value = i as f64 / buckets as f64;
983-
sum += value * hist[i] as f64;
984-
count += hist[i] as u64;
984+
sum += value * bin_count as f64;
985+
count += bin_count as u64;
985986
}
986987

987988
if count > 0 {

crates/invers-core/src/gpu/tests.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use super::*;
44
use crate::decoders::DecodedImage;
55

6+
#[allow(dead_code)]
67
const TOLERANCE: f32 = 1e-4; // Allow small floating-point variance
78

89
/// Generate a test gradient image
@@ -28,6 +29,8 @@ fn generate_test_gradient(width: u32, height: u32) -> DecodedImage {
2829
black_level: None,
2930
white_level: None,
3031
color_matrix: None,
32+
is_monochrome: false,
33+
source_is_grayscale: false,
3134
}
3235
}
3336

@@ -205,6 +208,8 @@ fn generate_test_negative(width: u32, height: u32) -> DecodedImage {
205208
black_level: None,
206209
white_level: None,
207210
color_matrix: None,
211+
is_monochrome: false,
212+
source_is_grayscale: false,
208213
}
209214
}
210215

@@ -253,6 +258,7 @@ fn create_test_options(use_gpu: bool) -> crate::models::ConvertOptions {
253258
auto_exposure_max_gain: 2.0,
254259
no_clip: true, // Preserve full range for comparison
255260
enable_auto_wb: false,
261+
auto_wb_strength: 0.5,
256262
use_gpu,
257263
}
258264
}

crates/invers-core/src/pipeline.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ pub fn process_image(
270270
let safe_exposure = options.exposure_compensation.min(1.0);
271271
if safe_exposure < 1.0 {
272272
for value in data.iter_mut() {
273-
*value = *value * safe_exposure;
273+
*value *= safe_exposure;
274274
}
275275
}
276276
if options.debug && options.exposure_compensation > 1.0 {
@@ -507,6 +507,7 @@ fn estimate_base_from_manual_roi(
507507
/// - Near-white clipped pixels (all channels > 0.95)
508508
/// - Very dark pixels (all channels < 0.05)
509509
/// - Bright grayscale pixels without color variation (not orange mask)
510+
///
510511
/// Filter results from base pixel filtering
511512
struct FilteredBasePixels {
512513
/// Valid pixels that passed filtering
@@ -1084,9 +1085,9 @@ fn estimate_base_from_histogram(image: &DecodedImage) -> Result<BaseEstimation,
10841085
let mut peak_bin = min_bin;
10851086
let mut peak_count = 0u32;
10861087

1087-
for bin in min_bin..=max_bin {
1088-
if hist[bin] > peak_count {
1089-
peak_count = hist[bin];
1088+
for (bin, &count) in hist.iter().enumerate().take(max_bin + 1).skip(min_bin) {
1089+
if count > peak_count {
1090+
peak_count = count;
10901091
peak_bin = bin;
10911092
}
10921093
}
@@ -1503,7 +1504,7 @@ pub fn invert_negative(
15031504
let mask_profile = base
15041505
.mask_profile
15051506
.clone()
1506-
.unwrap_or_else(crate::models::MaskProfile::default);
1507+
.unwrap_or_default();
15071508

15081509
// Calculate shadow floor values
15091510
let (_red_floor, green_floor, blue_floor) = mask_profile.calculate_shadow_floors();

0 commit comments

Comments
 (0)