Skip to content

Instantly share code, notes, and snippets.

@GorgeousOne
Last active February 14, 2024 19:06
Show Gist options
  • Save GorgeousOne/8058e050410b9f93923015a7deecb4b8 to your computer and use it in GitHub Desktop.
Save GorgeousOne/8058e050410b9f93923015a7deecb4b8 to your computer and use it in GitHub Desktop.
GUI for creating QR codes with a logo in the middle
import tkinter as tk
from tkinter import filedialog
import qrcode
from qrcode import constants as qr_const
from PIL import Image, ImageTk
import re
class MyGUI:
def __init__(self):
self.root = tk.Tk()
self.root.title("My GUI")
self.root.geometry("600x600") # Set the window size to 400x300 pixels
self.placeholder_img = Image.new("RGB", (300, 300), (255, 255, 255))
self.qr_data = ""
self.qr_img = self.placeholder_img
self.logo_img = None
self.create_widgets()
def create_widgets(self):
self.data_label = tk.Label(self.root, text="Enter a string:")
self.data_label.pack()
self.data_entry = tk.Entry(self.root)
self.data_entry.pack()
self.data_entry.bind("<KeyRelease>", self.on_data_change)
self.radio_var = tk.StringVar()
self.radio_var.set(qr_const.ERROR_CORRECT_Q) # Set the default value
self.radio_label = tk.Label(self.root, text="Choose an error correction option:")
self.radio_label.pack()
self.radio_button1 = tk.Radiobutton(self.root, text="Low (7%)", variable=self.radio_var, value=qr_const.ERROR_CORRECT_L, command=self.update_qr_img)
self.radio_button1.pack()
self.radio_button2 = tk.Radiobutton(self.root, text="Medium (10%)", variable=self.radio_var, value=qr_const.ERROR_CORRECT_M, command=self.update_qr_img)
self.radio_button2.pack()
self.radio_button3 = tk.Radiobutton(self.root, text="Quartile (25%)", variable=self.radio_var, value=qr_const.ERROR_CORRECT_Q, command=self.update_qr_img)
self.radio_button3.pack()
self.radio_button4 = tk.Radiobutton(self.root, text="High (30%)", variable=self.radio_var, value=qr_const.ERROR_CORRECT_H, command=self.update_qr_img)
self.radio_button4.pack()
self.logo_size_label = tk.Label(self.root, text="Choose logo size:")
self.logo_size_label.pack()
self.logo_size_slider = tk.Scale(self.root, from_=4, to=13, orient=tk.HORIZONTAL, command=self.on_logo_size_change)
self.logo_size_slider.pack()
self.logo_size_slider.set(5)
self.logo_scale_label = tk.Label(self.root, text="Choose logo scale:")
self.logo_scale_label.pack()
self.logo_scale_slider = tk.Scale(self.root, from_=50, to=150, orient=tk.HORIZONTAL, resolution=5, command=self.on_logo_size_change)
self.logo_scale_slider.pack()
self.logo_scale_slider.set(100)
self.image_button = tk.Button(self.root, text="Load logo", command=self.load_image)
self.image_button.pack()
self.save_button = tk.Button(self.root, text="Save", command=self.save_qr_img)
self.save_button.pack()
thumbnail = ImageTk.PhotoImage(self.placeholder_img)
self.qr_label = tk.Label(self.root, image=thumbnail)
self.qr_label.image = thumbnail
self.qr_label.pack()
def update_qr_img(self):
if not self.qr_data:
self.qr_image = self.placeholder_img
return
code = qrcode.QRCode(error_correction=self.radio_var.get())
code.add_data(self.qr_data)
code.make()
self.qr_img = code.make_image().convert('RGB')
self.update_display()
def update_display(self):
display_img = self.qr_img.copy()
#double the size of the qr code
if self.logo_img:
self.paste_logo(display_img)
# convert to tkinter image
thumbnail = ImageTk.PhotoImage(display_img)
self.qr_label.config(image=thumbnail)
self.qr_label.image = thumbnail
def paste_logo(self, qr_img):
pixel_size = 10 # size of qr code pixels "qrcode" generates
cutout_size = self.logo_size_slider.get() * pixel_size
# whiteout the logo area
qr_img.paste(
(255, 255, 255),
(qr_img.width//2 - cutout_size//2,
qr_img.height//2 - cutout_size//2,
qr_img.width//2 + cutout_size//2,
qr_img.height//2 + cutout_size//2))
logo_scale = self.logo_scale_slider.get() / 100
logo_size = int((cutout_size - 2 * pixel_size) * logo_scale)
# resize logo
relative_scale = logo_size / max(self.logo_img.width, self.logo_img.height)
scaled_logo = self.logo_img.resize((
int(self.logo_img.width * relative_scale),
int(self.logo_img.height * relative_scale)))
# paste logo in the middle of the qr code
qr_img.paste(scaled_logo, (
qr_img.width//2 - logo_size//2,
qr_img.height//2 - logo_size//2))
def on_logo_size_change(self, *args):
self.update_display()
def on_data_change(self, *args):
# Get the string from the entry widget
self.qr_data = self.data_entry.get()
self.update_qr_img()
def load_image(self):
file_path = filedialog.askopenfilename(filetypes=[("Image Files", "*.png;*.jpg;*.jpeg")])
# load PIL image
self.logo_img = Image.open(file_path)
self.update_display()
def save_qr_img(self):
file_path = filedialog.asksaveasfilename(filetypes=[("Image File", "*.png;*.jpg;*.jpeg")])
if not re.search(r"\.(png|jpg|jpeg)$", file_path):
file_path += ".png"
final_img = self.qr_img.copy()
if self.logo_img:
self.paste_logo(final_img)
final_img.save(file_path)
def run(self):
self.root.mainloop()
if __name__ == "__main__":
gui = MyGUI()
gui.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment