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