Skip to content

Commit 6365c3b

Browse files
lilithclaude
andcommitted
deps: Rename butteraugli-oxide to butteraugli
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 8122724 commit 6365c3b

File tree

8 files changed

+357
-154
lines changed

8 files changed

+357
-154
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/codec-compare/src/analyze_image.rs

Lines changed: 65 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,40 @@
11
//! Analyze image characteristics to understand encoder preferences
22
3-
use std::path::Path;
3+
use std::path::{Path, PathBuf};
4+
5+
/// Get path to the codec-corpus directory.
6+
///
7+
/// # Panics
8+
/// Panics if directory cannot be found.
9+
fn get_corpus_dir() -> PathBuf {
10+
// Check environment variable first
11+
if let Ok(dir) = std::env::var("CODEC_CORPUS_DIR") {
12+
let path = PathBuf::from(dir);
13+
if path.exists() {
14+
return path;
15+
}
16+
}
17+
18+
// Check relative to manifest dir
19+
if let Ok(manifest) = std::env::var("CARGO_MANIFEST_DIR") {
20+
let candidates = [
21+
PathBuf::from(&manifest).join("../../codec-corpus"),
22+
PathBuf::from(&manifest).join("../../../codec-corpus"),
23+
PathBuf::from(&manifest).join("codec-corpus"),
24+
];
25+
for path in candidates {
26+
if path.exists() {
27+
return path;
28+
}
29+
}
30+
}
31+
32+
panic!(
33+
"codec-corpus directory not found.\n\
34+
Set CODEC_CORPUS_DIR environment variable or clone:\n\
35+
git clone --depth 1 https://github.com/imazen/codec-corpus ../codec-corpus"
36+
);
37+
}
438

539
fn load_image(path: &Path) -> Option<(Vec<u8>, usize, usize)> {
640
let img = image::open(path).ok()?;
@@ -15,7 +49,8 @@ fn analyze(rgb: &[u8], width: usize, height: usize) -> ImageStats {
1549
let pixels = width * height;
1650

1751
// Convert to grayscale for analysis
18-
let gray: Vec<f32> = rgb.chunks(3)
52+
let gray: Vec<f32> = rgb
53+
.chunks(3)
1954
.map(|p| 0.299 * p[0] as f32 + 0.587 * p[1] as f32 + 0.114 * p[2] as f32)
2055
.collect();
2156

@@ -25,8 +60,8 @@ fn analyze(rgb: &[u8], width: usize, height: usize) -> ImageStats {
2560

2661
// Edge strength (Sobel-like)
2762
let mut edge_sum = 0.0f32;
28-
for y in 1..height-1 {
29-
for x in 1..width-1 {
63+
for y in 1..height - 1 {
64+
for x in 1..width - 1 {
3065
let idx = y * width + x;
3166
let gx = gray[idx + 1] - gray[idx - 1];
3267
let gy = gray[idx + width] - gray[idx - width];
@@ -47,9 +82,11 @@ fn analyze(rgb: &[u8], width: usize, height: usize) -> ImageStats {
4782
}
4883
}
4984
let block_mean: f32 = block_pixels.iter().sum::<f32>() / 64.0;
50-
let block_var: f32 = block_pixels.iter()
85+
let block_var: f32 = block_pixels
86+
.iter()
5187
.map(|&v| (v - block_mean).powi(2))
52-
.sum::<f32>() / 64.0;
88+
.sum::<f32>()
89+
/ 64.0;
5390
block_variances.push(block_var);
5491
}
5592
}
@@ -64,9 +101,11 @@ fn analyze(rgb: &[u8], width: usize, height: usize) -> ImageStats {
64101

65102
// Variance of block variances (texture uniformity)
66103
let mean_block_var: f32 = block_variances.iter().sum::<f32>() / block_variances.len() as f32;
67-
let var_of_var: f32 = block_variances.iter()
104+
let var_of_var: f32 = block_variances
105+
.iter()
68106
.map(|&v| (v - mean_block_var).powi(2))
69-
.sum::<f32>() / block_variances.len() as f32;
107+
.sum::<f32>()
108+
/ block_variances.len() as f32;
70109

71110
ImageStats {
72111
mean_luminance: mean,
@@ -92,34 +131,38 @@ fn main() {
92131
let args: Vec<String> = std::env::args().collect();
93132

94133
let images: Vec<std::path::PathBuf> = if args.len() > 1 {
95-
args[1..].iter().map(|s| std::path::PathBuf::from(s)).collect()
134+
args[1..]
135+
.iter()
136+
.map(|s| std::path::PathBuf::from(s))
137+
.collect()
96138
} else {
97-
// Default Kodak outliers
98-
vec![
99-
"/home/lilith/work/codec-eval/codec-corpus/kodak/22.png",
100-
"/home/lilith/work/codec-eval/codec-corpus/kodak/20.png",
101-
"/home/lilith/work/codec-eval/codec-corpus/kodak/10.png",
102-
"/home/lilith/work/codec-eval/codec-corpus/kodak/23.png",
103-
"/home/lilith/work/codec-eval/codec-corpus/kodak/12.png",
104-
"/home/lilith/work/codec-eval/codec-corpus/kodak/8.png",
105-
].into_iter().map(std::path::PathBuf::from).collect()
139+
// Default Kodak outliers - find relative to manifest or via CODEC_CORPUS_DIR
140+
let corpus_dir = get_corpus_dir();
141+
vec!["22.png", "20.png", "10.png", "23.png", "12.png", "8.png"]
142+
.into_iter()
143+
.map(|name| corpus_dir.join("kodak").join(name))
144+
.collect()
106145
};
107146

108-
println!("{:>12} | {:>8} | {:>8} | {:>8} | {:>8} | {:>8} | {:>8}",
109-
"Image", "Mean", "Variance", "Edges", "Flat%", "Detail%", "TexUnif");
147+
println!(
148+
"{:>12} | {:>8} | {:>8} | {:>8} | {:>8} | {:>8} | {:>8}",
149+
"Image", "Mean", "Variance", "Edges", "Flat%", "Detail%", "TexUnif"
150+
);
110151
println!("{}", "-".repeat(85));
111152

112153
for path in images {
113154
if let Some((rgb, width, height)) = load_image(&path) {
114155
let stats = analyze(&rgb, width, height);
115-
println!("{:>12} | {:>8.1} | {:>8.1} | {:>8.2} | {:>8.1} | {:>8.1} | {:>8.1}",
156+
println!(
157+
"{:>12} | {:>8.1} | {:>8.1} | {:>8.2} | {:>8.1} | {:>8.1} | {:>8.1}",
116158
path.file_name().unwrap_or_default().to_string_lossy(),
117159
stats.mean_luminance,
118160
stats.global_variance,
119161
stats.edge_strength,
120162
stats.flat_block_pct,
121163
stats.detail_block_pct,
122-
stats.texture_uniformity);
164+
stats.texture_uniformity
165+
);
123166
}
124167
}
125168
}

0 commit comments

Comments
 (0)