|
1 | 1 | """ pyplots.ai |
2 | 2 | qrcode-basic: Basic QR Code Generator |
3 | | -Library: matplotlib 3.10.8 | Python 3.13.11 |
4 | | -Quality: 91/100 | Created: 2026-01-07 |
| 3 | +Library: matplotlib 3.10.8 | Python 3.14.3 |
| 4 | +Quality: 90/100 | Updated: 2026-04-07 |
5 | 5 | """ |
6 | 6 |
|
| 7 | +import matplotlib.patches as mpatches |
| 8 | +import matplotlib.patheffects as pe |
7 | 9 | import matplotlib.pyplot as plt |
8 | 10 | import numpy as np |
| 11 | +import qrcode |
| 12 | +from matplotlib.colors import ListedColormap |
| 13 | + |
| 14 | + |
| 15 | +# Data - Generate a real, scannable QR code encoding "https://pyplots.ai" |
| 16 | +content = "https://pyplots.ai" |
| 17 | + |
| 18 | +qr = qrcode.QRCode(version=1, error_correction=qrcode.constants.ERROR_CORRECT_M, box_size=1, border=4) |
| 19 | +qr.add_data(content) |
| 20 | +qr.make(fit=True) |
| 21 | + |
| 22 | +# Convert QR code to numpy matrix |
| 23 | +qr_matrix = np.array(qr.get_matrix(), dtype=int) |
| 24 | +rows, cols = qr_matrix.shape |
| 25 | + |
| 26 | +# Plot |
| 27 | +fig, ax = plt.subplots(figsize=(12, 12), facecolor="white") |
| 28 | + |
| 29 | +# Custom two-color colormap for crisp rendering |
| 30 | +qr_cmap = ListedColormap(["#FFFFFF", "#1A1A2E"]) |
| 31 | +ax.imshow(qr_matrix, cmap=qr_cmap, interpolation="nearest", vmin=0, vmax=1, aspect="equal") |
| 32 | + |
| 33 | +# Completely remove axes and all frame artifacts |
| 34 | +ax.set_axis_off() |
| 35 | +for spine in ax.spines.values(): |
| 36 | + spine.set_visible(False) |
| 37 | +ax.set_frame_on(False) |
| 38 | + |
| 39 | +# Decorative rounded-corner frame around the QR code using FancyBboxPatch |
| 40 | +padding = 0.8 |
| 41 | +frame = mpatches.FancyBboxPatch( |
| 42 | + (-padding, -padding), |
| 43 | + cols - 1 + 2 * padding, |
| 44 | + rows - 1 + 2 * padding, |
| 45 | + boxstyle=mpatches.BoxStyle.Round(pad=0.6, rounding_size=1.5), |
| 46 | + facecolor="none", |
| 47 | + edgecolor="#306998", |
| 48 | + linewidth=2.5, |
| 49 | + zorder=5, |
| 50 | +) |
| 51 | +ax.add_patch(frame) |
| 52 | + |
| 53 | +# Subtle shadow frame behind the main frame for depth |
| 54 | +shadow = mpatches.FancyBboxPatch( |
| 55 | + (-padding + 0.15, -padding + 0.15), |
| 56 | + cols - 1 + 2 * padding, |
| 57 | + rows - 1 + 2 * padding, |
| 58 | + boxstyle=mpatches.BoxStyle.Round(pad=0.6, rounding_size=1.5), |
| 59 | + facecolor="none", |
| 60 | + edgecolor="#306998", |
| 61 | + linewidth=2.5, |
| 62 | + alpha=0.15, |
| 63 | + zorder=4, |
| 64 | +) |
| 65 | +ax.add_patch(shadow) |
9 | 66 |
|
| 67 | +# Extend view to accommodate frame and annotations |
| 68 | +ax.set_xlim(-2.5, cols + 1.5) |
| 69 | +ax.set_ylim(rows + 1.5, -2.5) |
10 | 70 |
|
11 | | -# Data - Create a QR code-like pattern encoding "pyplots.ai" |
12 | | -# Note: This is a simplified visual representation of a QR code structure |
13 | | -np.random.seed(42) |
14 | | - |
15 | | -# QR code dimensions (Version 1: 21x21 modules) |
16 | | -size = 21 |
17 | | - |
18 | | -# Initialize the QR code matrix (0 = white, 1 = black) |
19 | | -qr_matrix = np.zeros((size, size), dtype=int) |
| 71 | +fig.subplots_adjust(left=0.06, right=0.94, top=0.87, bottom=0.14) |
20 | 72 |
|
21 | | -# Position Detection Patterns (finder patterns) - 7x7 in three corners |
22 | | -finder_pattern = np.array( |
23 | | - [ |
24 | | - [1, 1, 1, 1, 1, 1, 1], |
25 | | - [1, 0, 0, 0, 0, 0, 1], |
26 | | - [1, 0, 1, 1, 1, 0, 1], |
27 | | - [1, 0, 1, 1, 1, 0, 1], |
28 | | - [1, 0, 1, 1, 1, 0, 1], |
29 | | - [1, 0, 0, 0, 0, 0, 1], |
30 | | - [1, 1, 1, 1, 1, 1, 1], |
31 | | - ] |
| 73 | +# Title with patheffects for subtle glow |
| 74 | +title = ax.set_title( |
| 75 | + "qrcode-basic \u00b7 matplotlib \u00b7 pyplots.ai", fontsize=28, fontweight="bold", pad=30, color="#306998" |
| 76 | +) |
| 77 | +title.set_path_effects([pe.withStroke(linewidth=3, foreground="white"), pe.Normal()]) |
| 78 | + |
| 79 | +# Accent rule line using axhline in figure coordinates via fig.add_axes |
| 80 | +accent_ax = fig.add_axes([0.25, 0.105, 0.50, 0.002]) |
| 81 | +accent_ax.set_xlim(0, 1) |
| 82 | +accent_ax.set_ylim(0, 1) |
| 83 | +gradient = np.linspace(0, 1, 256).reshape(1, -1) |
| 84 | +accent_ax.imshow(gradient, aspect="auto", cmap=ListedColormap(["#306998", "#FFD43B"]), extent=[0, 1, 0, 1]) |
| 85 | +accent_ax.set_axis_off() |
| 86 | + |
| 87 | +# Metadata text with patheffects |
| 88 | +encoded_text = fig.text( |
| 89 | + 0.5, |
| 90 | + 0.085, |
| 91 | + f"Encoded: {content}", |
| 92 | + ha="center", |
| 93 | + fontsize=20, |
| 94 | + color="#444444", |
| 95 | + family="monospace", |
| 96 | + fontweight="medium", |
32 | 97 | ) |
| 98 | +encoded_text.set_path_effects([pe.withStroke(linewidth=2, foreground="white"), pe.Normal()]) |
33 | 99 |
|
34 | | -# Place finder patterns in three corners |
35 | | -qr_matrix[0:7, 0:7] = finder_pattern # Top-left |
36 | | -qr_matrix[0:7, size - 7 : size] = finder_pattern # Top-right |
37 | | -qr_matrix[size - 7 : size, 0:7] = finder_pattern # Bottom-left |
38 | | - |
39 | | -# Timing patterns (alternating black/white lines) |
40 | | -for i in range(8, size - 8): |
41 | | - qr_matrix[6, i] = i % 2 # Horizontal |
42 | | - qr_matrix[i, 6] = i % 2 # Vertical |
43 | | - |
44 | | -# Alignment pattern (5x5) for Version 2+ QR codes - placing one at center area |
45 | | -alignment = np.array([[1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 1, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1]]) |
46 | | - |
47 | | -# Place alignment pattern (avoiding finder patterns) |
48 | | -qr_matrix[size - 9 : size - 4, size - 9 : size - 4] = alignment |
49 | | - |
50 | | -# Separators (white border around finder patterns) - already 0 in initialization |
51 | | -# Format information areas (fixed patterns near finder patterns) |
52 | | -qr_matrix[8, 0:6] = [1, 0, 1, 0, 1, 0] |
53 | | -qr_matrix[8, 7:9] = [1, 1] |
54 | | -qr_matrix[0:6, 8] = [1, 0, 1, 0, 1, 0] |
55 | | -qr_matrix[7:9, 8] = [1, 1] |
56 | | - |
57 | | -# Data encoding area - fill with a pattern representing "pyplots.ai" |
58 | | -# Using deterministic pattern based on the URL characters |
59 | | -data_string = "https://pyplots.ai" |
60 | | -data_values = [ord(c) for c in data_string] |
61 | | - |
62 | | -# Fill data area with encoded pattern |
63 | | -data_idx = 0 |
64 | | -for row in range(8, size - 1): |
65 | | - for col in range(9, size - 1): |
66 | | - if qr_matrix[row, col] == 0: # Only fill empty cells |
67 | | - if row != 6 and col != 6: # Avoid timing patterns |
68 | | - # Create pattern from data |
69 | | - qr_matrix[row, col] = data_values[data_idx % len(data_values)] % 2 |
70 | | - data_idx += 1 |
71 | | - |
72 | | -# Add quiet zone (white border) by padding |
73 | | -quiet_zone = 4 |
74 | | -padded_size = size + 2 * quiet_zone |
75 | | -qr_with_border = np.zeros((padded_size, padded_size), dtype=int) |
76 | | -qr_with_border[quiet_zone : quiet_zone + size, quiet_zone : quiet_zone + size] = qr_matrix |
77 | | - |
78 | | -# Create figure (square format for QR code) |
79 | | -fig, ax = plt.subplots(figsize=(12, 12)) |
80 | | - |
81 | | -# Display QR code with high contrast black on white |
82 | | -ax.imshow(qr_with_border, cmap="gray_r", interpolation="nearest", vmin=0, vmax=1) |
83 | | - |
84 | | -# Remove axes for clean QR code appearance |
85 | | -ax.axis("off") |
86 | | - |
87 | | -# Add title |
88 | | -ax.set_title("qrcode-basic · matplotlib · pyplots.ai", fontsize=28, fontweight="bold", pad=30, color="#306998") |
89 | | - |
90 | | -# Add the encoded content as annotation below |
91 | | -fig.text(0.5, 0.06, f"Encoded: {data_string}", ha="center", fontsize=20, color="#555555", family="monospace") |
92 | | - |
93 | | -# Add note about structure |
94 | | -fig.text( |
95 | | - 0.5, 0.02, "QR Code Version 1 (21×21) with Error Correction Level M", ha="center", fontsize=14, color="#888888" |
| 100 | +version_info = ( |
| 101 | + f"QR Code Version {qr.version} ({qr_matrix.shape[0]}\u00d7{qr_matrix.shape[1]}) \u00b7 Error Correction Level M" |
96 | 102 | ) |
| 103 | +meta_text = fig.text(0.5, 0.04, version_info, ha="center", fontsize=16, color="#777777", style="italic") |
| 104 | +meta_text.set_path_effects([pe.withStroke(linewidth=1.5, foreground="white"), pe.Normal()]) |
97 | 105 |
|
98 | | -plt.tight_layout() |
99 | 106 | plt.savefig("plot.png", dpi=300, bbox_inches="tight", facecolor="white") |
0 commit comments