Skip to content

Commit 69880d3

Browse files
committed
Add gated degrade example for realistic jsQR-parity benchmarking
Verified side-by-side: anyd matches jsQR (reference decoder) on curved (cylinder half-arc to 0.9) + rotated + blurred + noisy + JPEG QRs at ~5px/module. The earlier real-photo failures were degraded screenshot crops that jsQR/ZXing/rqrr/zbar also cannot read — not a decoder gap.
1 parent b7727dd commit 69880d3

2 files changed

Lines changed: 47 additions & 0 deletions

File tree

‎Cargo.toml‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,7 @@ harness = false
4646
[[example]]
4747
name = "qrdebug"
4848
required-features = ["cli"]
49+
50+
[[example]]
51+
name = "degrade"
52+
required-features = ["cli"]

‎examples/degrade.rs‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Realistic-degradation harness: render a QR, warp/blur/noise it, write PNG.
2+
use anyd::codes::qr::{EcLevel, QrEncoder};
3+
use anyd::render::render;
4+
use anyd::traits::Encode;
5+
use anyd::transform::{self, Axis, Rng};
6+
7+
fn main() {
8+
let mut a = std::env::args().skip(1);
9+
let out = a.next().expect("out.png");
10+
let cyl: f32 = a.next().unwrap().parse().unwrap();
11+
let rot: f32 = a.next().unwrap().parse().unwrap();
12+
let blur: f32 = a.next().unwrap().parse().unwrap();
13+
let noise: f32 = a.next().unwrap().parse().unwrap();
14+
let scale: usize = a.next().map(|s| s.parse().unwrap()).unwrap_or(6);
15+
16+
let e = QrEncoder::new();
17+
let sym = e.build_text("https://anyd.dev/x", EcLevel::M).unwrap();
18+
let enc = e.encode(&sym).unwrap();
19+
let mut img = render(&enc, scale);
20+
if cyl != 0.0 {
21+
img = transform::cylinder(&img, cyl, Axis::Vertical);
22+
}
23+
if rot != 0.0 {
24+
img = transform::rotate(&img, rot);
25+
}
26+
if blur != 0.0 {
27+
img = transform::gaussian_blur(&img, blur);
28+
}
29+
if noise != 0.0 {
30+
let mut rng = Rng::new(42);
31+
img = transform::add_noise(&img, noise, &mut rng);
32+
}
33+
let png = oxideav_png::PngImage {
34+
width: img.width() as u32,
35+
height: img.height() as u32,
36+
pixel_format: oxideav_png::PngPixelFormat::Gray8,
37+
stride: img.width(),
38+
data: img.pixels().to_vec(),
39+
palette: Vec::new(),
40+
};
41+
std::fs::write(&out, oxideav_png::encode_png_image(&png).unwrap()).unwrap();
42+
println!("wrote {out} {}x{}", img.width(), img.height());
43+
}

0 commit comments

Comments
 (0)