Skip to content

Commit 347b44d

Browse files
committed
新增自动分析功能
1 parent a02571a commit 347b44d

4 files changed

Lines changed: 94 additions & 3 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "arnold_decoder"
33
authors = ["Aristore"]
4-
version = "1.0.0"
4+
version = "2.0.0"
55
edition = "2024"
66

77
[dependencies]

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
[![Made with Rust](https://img.shields.io/badge/Made%20with-Rust-orange?style=for-the-badge&logo=rust)](https://www.rust-lang.org/)
44

5-
一个用于暴力破解**猫变换(Arnold's Cat Map)**加密图像的命令行工具。
5+
一个用于暴力破解 **猫变换(Arnold's Cat Map)** 加密图像的命令行工具。
66

7-
当你拿到一张被阿诺德变换打乱的图片,但不知道加密时使用的**变换次数(t)****参数a****参数b**时,本工具可以帮助你快速找回原图。
7+
当你拿到一张被猫变换打乱的图片,但不知道加密时使用的**变换次数(t)****参数a****参数b**时,本工具可以帮助你快速找回原图。
88

99
![1](./images/1.png)
1010

images/1.png

44.3 KB
Loading

src/main.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,92 @@ fn get_user_range(prompt: &str) -> Result<std::ops::Range<i64>> {
8888
}
8989
}
9090

91+
// 计算图像的平滑度得分,得分越低表示图像相邻像素颜色差异越小,图像越平滑,越可能是正确结果
92+
fn calculate_smoothness_score(image: &RgbImage) -> f64 {
93+
let (width, height) = image.dimensions();
94+
if width < 2 || height < 2 {
95+
return f64::MAX;
96+
}
97+
98+
let mut total_diff: u64 = 0;
99+
100+
// 遍历几乎所有像素,计算其与右侧和下方像素的差异
101+
for y in 0..height - 1 {
102+
for x in 0..width - 1 {
103+
let p1 = image.get_pixel(x, y);
104+
let p2 = image.get_pixel(x + 1, y); // 右侧像素
105+
let p3 = image.get_pixel(x, y + 1); // 下方像素
106+
107+
// 计算RGB通道的绝对差值之和
108+
let diff_h = (p1[0] as i16 - p2[0] as i16).abs() as u32 +
109+
(p1[1] as i16 - p2[1] as i16).abs() as u32 +
110+
(p1[2] as i16 - p2[2] as i16).abs() as u32;
111+
112+
let diff_v = (p1[0] as i16 - p3[0] as i16).abs() as u32 +
113+
(p1[1] as i16 - p3[1] as i16).abs() as u32 +
114+
(p1[2] as i16 - p3[2] as i16).abs() as u32;
115+
116+
total_diff += (diff_h + diff_v) as u64;
117+
}
118+
}
119+
120+
// 将总差异标准化,避免图像尺寸影响得分
121+
let num_comparisons = (width - 1) * (height - 1) * 2;
122+
if num_comparisons == 0 {
123+
return f64::MAX;
124+
}
125+
total_diff as f64 / num_comparisons as f64
126+
}
127+
128+
// 分析输出目录中的所有图像,并根据平滑度得分排序,列出最可能的结果
129+
fn analyze_results(output_dir: &Path) -> Result<()> {
130+
let entries = fs::read_dir(output_dir)
131+
.with_context(|| format!("❌ 无法读取分析目录: {:?}", output_dir))?
132+
.filter_map(Result::ok)
133+
.filter(|e| e.path().extension().and_then(|s| s.to_str()) == Some("png"))
134+
.collect::<Vec<_>>();
135+
136+
if entries.is_empty() {
137+
println!("🤷‍♀️ 在输出目录中未找到任何 .png 文件进行分析");
138+
return Ok(());
139+
}
140+
141+
let bar_style = ProgressStyle::default_bar()
142+
.template("{spinner:.cyan} [{elapsed_precise}] [{bar:40.yellow/red}] {pos}/{len} ({percent}%) 分析中: {msg}")
143+
.unwrap()
144+
.progress_chars("=> ");
145+
let bar = ProgressBar::new(entries.len() as u64).with_style(bar_style);
146+
147+
let mut scored_images: Vec<(PathBuf, f64)> = entries
148+
.par_iter()
149+
.progress_with(bar)
150+
.filter_map(|entry| {
151+
let path = entry.path();
152+
if let Ok(image) = image::open(&path) {
153+
let score = calculate_smoothness_score(&image.to_rgb8());
154+
Some((path, score))
155+
} else {
156+
None
157+
}
158+
})
159+
.collect();
160+
161+
// 根据平滑度进行升序排序,得分越低越好
162+
scored_images.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
163+
164+
println!("\n🔍 分析完成,以下是可能性最高的 5 个结果 (得分越低越可能是正确结果):");
165+
println!("---------------------------------------------------------------------------------");
166+
167+
for (path, score) in scored_images.iter().take(5) {
168+
if let Some(filename) = path.file_name().and_then(|s| s.to_str()) {
169+
println!(" - 📄 文件: {:<25} | 📉 得分: {:.2}", filename, score);
170+
}
171+
}
172+
println!("---------------------------------------------------------------------------------");
173+
174+
Ok(())
175+
}
176+
91177
fn main() -> Result<()> {
92178
println!(r"");
93179
println!(r"================================================================================================================");
@@ -182,6 +268,11 @@ fn main() -> Result<()> {
182268
println!("\n⏱️ 用时: {:.2} 秒", duration.as_secs_f64());
183269

184270
println!("🎉 处理完成");
271+
272+
if let Err(e) = analyze_results(&output_dir) {
273+
eprintln!("❌ 分析过程中发生错误: {:?}", e);
274+
}
275+
185276
pause_before_exit();
186277
Ok(())
187278
}

0 commit comments

Comments
 (0)