Commit c9f1a8b9db876b398efec3da47faa9e934e285e5

Cléo Rebert 2024-03-08T16:53:40

Update base64 create Signed-off-by: Cléo Rebert <cleo.rebert@gmail.com>

diff --git a/qrcodegen-image/CHANGELOG.md b/qrcodegen-image/CHANGELOG.md
index f4b2009..b4d6dfb 100644
--- a/qrcodegen-image/CHANGELOG.md
+++ b/qrcodegen-image/CHANGELOG.md
@@ -1,5 +1,12 @@
 # Changelog
 
+## [1.4.0](https://github.com/constantoine/totp-rs/releases/tag/qrcodegen-image%2Fv1.4.0) (08/03/2024)
+
+### What's new
+
+- `draw_canvas` is now 15%(!) faster on my machine after optimizing the "drawing_square" loop.
+- Updated `base64` crate to `0.22`.
+
 ## [1.3.0](https://github.com/constantoine/totp-rs/releases/tag/qrcodegen-image%2Fv1.3.0) (19/01/2024)
 
 ### What's new
diff --git a/qrcodegen-image/Cargo.toml b/qrcodegen-image/Cargo.toml
index 9968cc4..2221261 100644
--- a/qrcodegen-image/Cargo.toml
+++ b/qrcodegen-image/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "qrcodegen-image"
-version = "1.3.0"
+version = "1.4.0"
 edition = "2021"
 authors = ["Cleo Rebert <cleo.rebert@gmail.com>"]
 rust-version = "1.61"
@@ -19,7 +19,7 @@ base64 = ["dep:base64"]
 [dependencies]
 qrcodegen = "1.8"
 image = { version = "0.24", features = ["png"], default-features = false}
-base64 = { version = "0.21", optional = true }
+base64 = { version = "0.22", optional = true }
 
 [dev-dependencies]
 criterion = { version = "0.5", features = ["html_reports"] }
diff --git a/qrcodegen-image/benches/benches.rs b/qrcodegen-image/benches/benches.rs
index c29f7fe..c16898c 100644
--- a/qrcodegen-image/benches/benches.rs
+++ b/qrcodegen-image/benches/benches.rs
@@ -1,6 +1,6 @@
 use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
 
-fn criterion_benchmark(c: &mut Criterion) {
+fn canvas_benchmark(c: &mut Criterion) {
     let input = qrcodegen::QrCode::encode_text("otpauth://totp/GitHub:test?issuer=GitHub&secret=KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ&digits=8&period=60&algorithm=SHA256", qrcodegen::QrCodeEcc::Medium).unwrap();
     c.bench_with_input(
         BenchmarkId::new("qrcodegen-image", "draw_canvas"),
@@ -13,5 +13,18 @@ fn criterion_benchmark(c: &mut Criterion) {
     );
 }
 
-criterion_group!(benches, criterion_benchmark);
+fn png_benchmark(c: &mut Criterion) {
+    let input = "otpauth://totp/GitHub:test?issuer=GitHub&secret=KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ&digits=8&period=60&algorithm=SHA256";
+    c.bench_with_input(
+        BenchmarkId::new("qrcodegen-image", "draw_png"),
+        black_box(&input),
+        |b, i| {
+            b.iter(|| {
+                let _img = qrcodegen_image::draw_png(i);
+            })
+        },
+    );
+}
+
+criterion_group!(benches, canvas_benchmark, png_benchmark);
 criterion_main!(benches);
diff --git a/qrcodegen-image/src/lib.rs b/qrcodegen-image/src/lib.rs
index 8208216..68cbacd 100644
--- a/qrcodegen-image/src/lib.rs
+++ b/qrcodegen-image/src/lib.rs
@@ -11,22 +11,16 @@ pub fn draw_canvas(qr: qrcodegen::QrCode) -> image::ImageBuffer<Luma<u8>, Vec<u8
     // "+ 8 * 8" is here to add padding (the white border around the QRCode)
     // As some QRCode readers don't work without padding
     let image_size = size * 8 + 8 * 8;
-    let mut canvas = image::GrayImage::new(image_size, image_size);
-
-    // Draw the border
-    for pixel in canvas.pixels_mut() {
-        *pixel = Luma([255]);
-    }
+    let mut canvas = image::GrayImage::from_pixel(image_size, image_size, Luma([255]));
 
     let raw = canvas.as_mut();
 
     // The QR inside the white border
     for x_qr in 0..size {
         for y_qr in 0..size {
-            // The canvas is a grayscale image without alpha. Hence it's only one 8-bits byte longs
-            // This clever trick to one-line the value was achieved with advanced mathematics
-            // And deep understanding of Boolean algebra.
-            let val = !qr.get_module(x_qr as i32, y_qr as i32) as u8 * 255;
+            if !qr.get_module(x_qr as i32, y_qr as i32) {
+                continue
+            }
 
             // Multiply coordinates by width of pixels
             // And take into account the 8*4 padding on top and left side
@@ -36,7 +30,7 @@ pub fn draw_canvas(qr: qrcodegen::QrCode) -> image::ImageBuffer<Luma<u8>, Vec<u8
             // Draw a 8-pixels-wide square
             for y_img in y_start..y_start + 8 {
                 let start = (x_start + y_img * image_size) as usize;
-                raw[start..start + 8].copy_from_slice(&[val; 8]);
+                raw[start..start + 8].copy_from_slice(&[0; 8]);
             }
         }
     }