qrcode_rs/render/
mod.rs

1//! Render a QR code into image.
2
3use crate::cast::As;
4use crate::types::Color;
5use std::cmp::max;
6
7pub mod image;
8pub mod string;
9pub mod svg;
10pub mod unicode;
11
12//------------------------------------------------------------------------------
13//{{{ Pixel trait
14
15/// Abstraction of an image pixel.
16pub trait Pixel: Copy + Sized {
17    /// Type of the finalized image.
18    type Image: Sized + 'static;
19
20    /// The type that stores an intermediate buffer before finalizing to a
21    /// concrete image
22    type Canvas: Canvas<Pixel = Self, Image = Self::Image>;
23
24    /// Obtains the default module size. The result must be at least 1×1.
25    fn default_unit_size() -> (u32, u32) {
26        (8, 8)
27    }
28
29    /// Obtains the default pixel color when a module is dark or light.
30    fn default_color(color: Color) -> Self;
31}
32
33/// Rendering canvas of a QR code image.
34pub trait Canvas: Sized {
35    type Pixel: Sized;
36    type Image: Sized;
37
38    /// Constructs a new canvas of the given dimensions.
39    fn new(width: u32, height: u32, dark_pixel: Self::Pixel, light_pixel: Self::Pixel) -> Self;
40
41    /// Draws a single dark pixel at the (x, y) coordinate.
42    fn draw_dark_pixel(&mut self, x: u32, y: u32);
43
44    fn draw_dark_rect(&mut self, left: u32, top: u32, width: u32, height: u32) {
45        for y in top..(top + height) {
46            for x in left..(left + width) {
47                self.draw_dark_pixel(x, y);
48            }
49        }
50    }
51
52    /// Finalize the canvas to a real image.
53    fn into_image(self) -> Self::Image;
54}
55
56//}}}
57//------------------------------------------------------------------------------
58//{{{ Renderer
59
60/// A QR code renderer. This is a builder type which converts a bool-vector into
61/// an image.
62pub struct Renderer<'a, P: Pixel> {
63    content: &'a [Color],
64    modules_count: u32, // <- we call it `modules_count` here to avoid ambiguity of `width`.
65    quiet_zone: u32,
66    module_size: (u32, u32),
67
68    dark_color: P,
69    light_color: P,
70    has_quiet_zone: bool,
71}
72
73impl<'a, P: Pixel> Renderer<'a, P> {
74    /// Creates a new renderer.
75    ///
76    /// # Panics
77    /// panics if content is not `modules_count` squared big
78    pub fn new(content: &'a [Color], modules_count: usize, quiet_zone: u32) -> Renderer<'a, P> {
79        assert_eq!(modules_count * modules_count, content.len());
80        Renderer {
81            content,
82            modules_count: modules_count.as_u32(),
83            quiet_zone,
84            module_size: P::default_unit_size(),
85            dark_color: P::default_color(Color::Dark),
86            light_color: P::default_color(Color::Light),
87            has_quiet_zone: true,
88        }
89    }
90
91    /// Sets color of a dark module. Default is opaque black.
92    pub fn dark_color(&mut self, color: P) -> &mut Self {
93        self.dark_color = color;
94        self
95    }
96
97    /// Sets color of a light module. Default is opaque white.
98    pub fn light_color(&mut self, color: P) -> &mut Self {
99        self.light_color = color;
100        self
101    }
102
103    /// Whether to include the quiet zone in the generated image.
104    pub fn quiet_zone(&mut self, has_quiet_zone: bool) -> &mut Self {
105        self.has_quiet_zone = has_quiet_zone;
106        self
107    }
108
109    /// Sets the size of each module in pixels. Default is 8px.
110    #[deprecated(since = "0.4.0", note = "use `.module_dimensions(width, width)` instead")]
111    pub fn module_size(&mut self, width: u32) -> &mut Self {
112        self.module_dimensions(width, width)
113    }
114
115    /// Sets the size of each module in pixels. Default is 8×8.
116    pub fn module_dimensions(&mut self, width: u32, height: u32) -> &mut Self {
117        self.module_size = (max(width, 1), max(height, 1));
118        self
119    }
120
121    #[deprecated(since = "0.4.0", note = "use `.min_dimensions(width, width)` instead")]
122    pub fn min_width(&mut self, width: u32) -> &mut Self {
123        self.min_dimensions(width, width)
124    }
125
126    /// Sets the minimum total image size in pixels, including the quiet zone if
127    /// applicable. The renderer will try to find the dimension as small as
128    /// possible, such that each module in the QR code has uniform size (no
129    /// distortion).
130    ///
131    /// For instance, a version 1 QR code has 19 modules across including the
132    /// quiet zone. If we request an image of size ≥200×200, we get that each
133    /// module's size should be 11×11, so the actual image size will be 209×209.
134    pub fn min_dimensions(&mut self, width: u32, height: u32) -> &mut Self {
135        let quiet_zone = if self.has_quiet_zone { 2 } else { 0 } * self.quiet_zone;
136        let width_in_modules = self.modules_count + quiet_zone;
137        let unit_width = (width + width_in_modules - 1) / width_in_modules;
138        let unit_height = (height + width_in_modules - 1) / width_in_modules;
139        self.module_dimensions(unit_width, unit_height)
140    }
141
142    /// Sets the maximum total image size in pixels, including the quiet zone if
143    /// applicable. The renderer will try to find the dimension as large as
144    /// possible, such that each module in the QR code has uniform size (no
145    /// distortion).
146    ///
147    /// For instance, a version 1 QR code has 19 modules across including the
148    /// quiet zone. If we request an image of size ≤200×200, we get that each
149    /// module's size should be 10×10, so the actual image size will be 190×190.
150    ///
151    /// The module size is at least 1×1, so if the restriction is too small, the
152    /// final image *can* be larger than the input.
153    pub fn max_dimensions(&mut self, width: u32, height: u32) -> &mut Self {
154        let quiet_zone = if self.has_quiet_zone { 2 } else { 0 } * self.quiet_zone;
155        let width_in_modules = self.modules_count + quiet_zone;
156        let unit_width = width / width_in_modules;
157        let unit_height = height / width_in_modules;
158        self.module_dimensions(unit_width, unit_height)
159    }
160
161    /// Renders the QR code into an image.
162    #[deprecated(since = "0.4.0", note = "renamed to `.build()` to de-emphasize the image connection")]
163    pub fn to_image(&self) -> P::Image {
164        self.build()
165    }
166
167    /// Renders the QR code into an image.
168    pub fn build(&self) -> P::Image {
169        let w = self.modules_count;
170        let qz = if self.has_quiet_zone { self.quiet_zone } else { 0 };
171        let width = w + 2 * qz;
172
173        let (mw, mh) = self.module_size;
174        let real_width = width * mw;
175        let real_height = width * mh;
176
177        let mut canvas = P::Canvas::new(real_width, real_height, self.dark_color, self.light_color);
178        let mut i = 0;
179        for y in 0..width {
180            for x in 0..width {
181                if qz <= x && x < w + qz && qz <= y && y < w + qz {
182                    if self.content[i] != Color::Light {
183                        canvas.draw_dark_rect(x * mw, y * mh, mw, mh);
184                    }
185                    i += 1;
186                }
187            }
188        }
189
190        canvas.into_image()
191    }
192}
193
194//}}}