qrcode_png/
lib.rs

1//! Create a QR code
2//! ```
3//! use qrcode_png::{QrCode, QrCodeEcc, Color};
4//!
5//! let mut qrcode = QrCode::new(b"Hello Rust !", QrCodeEcc::Medium).unwrap();
6//!
7//! qrcode.zoom(10).margin(10);
8//!
9//! // -------- Bitmap
10//! let buf = qrcode.generate(Color::Bitmap(false, true)).unwrap();
11//! std::fs::write("./qrcode.bitmap.png", buf).unwrap();
12//!
13//! // -------- Grayscale
14//! let buf = qrcode.generate(Color::Grayscale(0, 255)).unwrap();
15//! std::fs::write("./qrcode.grayscale.png", buf).unwrap();
16//!
17//! // -------- RGB
18//! let buf = qrcode
19//!     .generate(Color::Rgb([3, 169, 244], [113, 140, 0]))
20//!     .unwrap();
21//! std::fs::write("./qrcode.rgb.png", buf).unwrap();
22//!
23//! // -------- RGBA
24//! let buf = qrcode
25//!     .generate(Color::Rgba([137, 89, 168, 255], [255, 255, 255, 0]))
26//!     .unwrap();
27//! std::fs::write("./qrcode.rgba.png", buf).unwrap();
28//! ```
29
30mod image;
31
32pub use image::Color;
33use image::Png;
34use png::EncodingError;
35pub use qrcodegen::QrCodeEcc;
36use qrcodegen::{DataTooLong, QrCode as QrCode_};
37
38/// Define QR code
39#[derive(Clone)]
40pub struct QrCode {
41    // QR Code
42    qr: QrCode_,
43    // Zoom factor
44    zoom: u32,
45    // Margin of the QR code from the picture
46    margin: u32,
47}
48
49impl QrCode {
50    /// Create a QR code
51    pub fn new<T: AsRef<[u8]>>(content: T, ecl: QrCodeEcc) -> Result<Self, DataTooLong> {
52        let qr = QrCode_::encode_binary(content.as_ref(), ecl)?;
53
54        Ok(Self {
55            qr,
56            zoom: 1,
57            margin: 0,
58        })
59    }
60
61    /// Enlarge the QR code according to the original scale,
62    /// Default value: 1
63    pub fn zoom(&mut self, zoom: u32) -> &mut Self {
64        assert_ne!(zoom, 0, "The minimum value is 1");
65        self.zoom = zoom;
66        self
67    }
68
69    /// Set the distance between the QR code and the edge of the picture
70    pub fn margin(&mut self, margin: u32) -> &mut Self {
71        self.margin = margin;
72        self
73    }
74
75    /// Get png data of QR code
76    pub fn generate(&self, color: Color) -> Result<Vec<u8>, EncodingError> {
77        let size = self.qr.size() as u32 * self.zoom + self.margin * 2;
78
79        let mut image = Png::new(size as usize, size as usize, color);
80
81        for x in 0..self.qr.size() {
82            for y in 0..self.qr.size() {
83                if self.qr.get_module(x, y) {
84                    let x_start = (x as u32 * self.zoom) + self.margin;
85                    let y_start = (y as u32 * self.zoom) + self.margin;
86
87                    for x in x_start..x_start + self.zoom {
88                        for y in y_start..y_start + self.zoom {
89                            image.set_color(x as usize, y as usize);
90                        }
91                    }
92                }
93            }
94        }
95
96        image.encode()
97    }
98}