| Crates.io | fuqr |
| lib.rs | fuqr |
| version | 1.0.0 |
| created_at | 2024-09-05 21:18:07.623192+00 |
| updated_at | 2024-10-09 14:22:55.074267+00 |
| description | feeling unemployed qr code generator |
| homepage | |
| repository | https://github.com/zhengkyl/fuqr |
| max_upload_size | |
| id | 1365172 |
| size | 124,758 |
feeling unemployed qr code generator
let qr_code = generate("https://github.com/zhengkyl/fuqr", &QrOptions::new()).unwrap();
This is what QrOptions::new() looks like.
QrOptions {
min_version: Version(1),
strict_version: false,
min_ecl: ECL::Low,
strict_ecl: false,
mode: None, // None = automatically determined
mask: None, // None = automatically determined
}
generate() has two possible errors.
QrError::InvalidEncoding occurs if Mode::Numeric or Mode::Alphanumeric is specified and the input string contains invalid characters. None or Mode::Byte will not error.
QrError::ExceedsMaxCapacity is what it sounds like, but unless strict_version is set to true, this is very hard to trigger. The lower limit is exceeding 1273 characters with Mode::Byte and ECL::High. See capacity table for specifics.
Based on Russ Cox's QArt codes with one improvement. The decoded message doesn't contain extra garbage data, because only the padding bits are manipulated. I first saw this improvement from https://github.com/xyzzy/qrpicture (actual code not available).
let version = Version::new(13);
let qr_width = version.0 * 4 + 17;
let pixel_weights = vec![WeightPixel::new(false, 0); qr_width * qr_width];
let qr_code = generate_qart(
"https://github.com/zhengkyl/fuqr",
&QrOptions::new().min_version(version),
&pixel_weights
).unwrap();
generate_qart() has the same errors as generate() along with QartError::InvalidPixelWeights if the size of pixel_weights doesn't match the size of the QR code matrix.
// This returns None if input string exceeds max capacity
let data = Data::new(
"https://github.com/zhengkyl/fuqr",
Mode::Byte,
Version(1), // minimum Version
ECL::Low, // minimum ECL
).unwrap();
// OR
let data = Data::new_verbose(
"https://github.com/zhengkyl/fuqr",
Mode::Byte,
Version(1),
true, // strict Version
ECL::Low,
true, // strict ECL
).unwrap();
// Pass None to determine and use "best" mask
let qr_code = QrCode::new(data, Some(Mask::M1));
The encoding Mode must be specified and no errors are thrown if it's invalid. This is fine because it's probably always Mode::Byte.
The strict arguments force Version and ECL to not upgrade. There is no real usecase for this.
// data from above
let mask = Mask::M0;
let bit_info = BitInfo::new(data.mode, data.version, data.ecl, mask);
BitInfo is like QrCode, but it stores the role of each bit/pixel for the specified Mode, Version, ECL, Mask combination. Specifically for data pixels, it tracks whether it is a data, error correction, or remainder bit, as well as its error correction block and index within said block.
All example code is WIP and in a very unpolished state.
/examples/bad_apple.rsAnimated QArt codes.
| Naive (low scannability) | Patterns + Low FPS |
|---|---|
![]() |
![]() |
# place video at ./examples/bad_apple/bad_apple.mp4
# i'm using the 3:40 one
# generates frames in ./examples/bad_apple/frames
cargo run --example bad_apple
# combines frames into mp4
ffmpeg -framerate 5 -pattern_type glob -i 'examples/bad_apple/frames/*.png' -c:v libx264 -pix_fmt yuv420p -vf "scale=iw*10:ih*10:flags=neighbor" frames.mp4
# combines frames with audio
ffmpeg -i frames.mp4 -i examples/bad_apple/bad_apple.mp4 -map 0:v:0 -map 1:a:0 -c:v copy -c:a aac -shortest out.mp4
/examples/scale.rsScaling modules based on position.
| Circle | Stripes | Waves |
|---|---|---|
![]() |
![]() |
![]() |
/examples/weave.rsNo need to stick to a boring pixel grid.
| Thick | Thin | Diagonal |
|---|---|---|
![]() |
![]() |
![]() |
/examples/layers.rsLayering is neat, but it can seriously degrade scanning ability if done without care.
See Halftone QR Codes, Micrography QR Codes, Amazing QR for more thoughtful implementations with high scannability.
| Background | Minimalist | Improved scannability |
|---|---|---|
![]() |
![]() |
![]() |
| Have | Some | More |
|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
My benchmarks seem to vary ~30% from run to run. My takeaway is that fuqr is kinda slow, but this is probably not the bottleneck.
| Test | Implementation | Time | Compared to fast_qr |
|---|---|---|---|
| V03H | fuqr | 71.225 - 73.230 µs | ~1.01x slower |
| qrcode | 541.65 - 569.61 µs | ~7.8x slower | |
| fast_qr | 70.581 - 72.627 µs | 1.0 (Fastest) | |
| V10H | fuqr | 365.81 - 372.89 µs | ~1.4x slower |
| qrcode | 2.2897 - 2.3480 ms | ~8.7x slower | |
| fast_qr | 262.86 - 270.61 µs | 1.0 (Fastest) | |
| V40H | fuqr | 3.0942 - 3.1684 ms | ~1.3x slower |
| qrcode | 21.502 - 21.952 ms | ~8.8x slower | |
| fast_qr | 2.4293 - 2.4919 ms | 1.0 (Fastest) |