286 lines
9.1 KiB
Python
286 lines
9.1 KiB
Python
"""
|
|
QR Code Generator - Streamlit Application
|
|
|
|
A web application for generating QR codes with optional logo overlay
|
|
and export in multiple formats and resolutions.
|
|
"""
|
|
|
|
import streamlit as st
|
|
from PIL import Image
|
|
import io
|
|
from utils.qr_generator import QRCodeGenerator
|
|
from utils.wifi_qr import WiFiQRCode
|
|
|
|
|
|
# Page configuration
|
|
st.set_page_config(
|
|
page_title="QR Code Generator",
|
|
page_icon="📱",
|
|
layout="centered",
|
|
initial_sidebar_state="expanded"
|
|
)
|
|
|
|
|
|
def main():
|
|
"""Main application function."""
|
|
st.title("QR Code Generator")
|
|
st.markdown("Generate professional QR codes with optional logo overlay")
|
|
|
|
# Sidebar configuration
|
|
with st.sidebar:
|
|
st.header("Configuration")
|
|
|
|
# Error correction level
|
|
error_correction = st.selectbox(
|
|
"Error Correction Level",
|
|
options=["L (7%)", "M (15%)", "Q (25%)", "H (30%)"],
|
|
index=3,
|
|
help="Higher levels allow more damage/obscurity. Use H (30%) for logos."
|
|
)
|
|
error_level = error_correction[0]
|
|
|
|
# QR code appearance
|
|
st.subheader("Appearance")
|
|
fill_color = st.color_picker("QR Code Color", "#000000")
|
|
back_color = st.color_picker("Background Color", "#FFFFFF")
|
|
|
|
# Export settings
|
|
st.subheader("Export Settings")
|
|
export_format = st.selectbox(
|
|
"Format",
|
|
options=["PNG", "JPEG", "SVG"],
|
|
help="SVG is vector format (scalable), PNG/JPEG are raster formats"
|
|
)
|
|
|
|
if export_format in ["PNG", "JPEG"]:
|
|
# Define resolution options
|
|
resolution_labels = {
|
|
500: "Low (500px)",
|
|
1000: "Medium (1000px)",
|
|
2000: "High (2000px)",
|
|
4000: "Ultra (4000px)"
|
|
}
|
|
target_size = st.select_slider(
|
|
"Resolution",
|
|
options=[500, 1000, 2000, 4000],
|
|
value=500, # Default to High
|
|
format_func=lambda x: resolution_labels[x]
|
|
)
|
|
else:
|
|
svg_scale = st.slider(
|
|
"SVG Scale",
|
|
min_value=5,
|
|
max_value=20,
|
|
value=10,
|
|
help="Scale factor for SVG output"
|
|
)
|
|
|
|
# Main content area
|
|
st.divider()
|
|
|
|
# Mode selection
|
|
qr_mode = st.radio(
|
|
"QR Code Type",
|
|
options=["URL", "WiFi"],
|
|
horizontal=True,
|
|
help="Choose what type of QR code to generate"
|
|
)
|
|
|
|
st.divider()
|
|
|
|
# Content input based on mode
|
|
if qr_mode == "URL":
|
|
# URL input
|
|
url = st.text_input(
|
|
"Enter URL",
|
|
placeholder="https://example.com",
|
|
help="Enter the URL you want to encode in the QR code"
|
|
)
|
|
qr_content = url
|
|
else:
|
|
# WiFi input fields
|
|
st.subheader("WiFi Network Details")
|
|
|
|
col1, col2 = st.columns(2)
|
|
|
|
with col1:
|
|
wifi_ssid = st.text_input(
|
|
"Network Name (SSID)",
|
|
placeholder="MyWiFiNetwork",
|
|
help="The name of your WiFi network"
|
|
)
|
|
|
|
wifi_security = st.selectbox(
|
|
"Security Type",
|
|
options=["WPA/WPA2", "WEP", "None (Open)"],
|
|
help="WiFi security/encryption type"
|
|
)
|
|
|
|
with col2:
|
|
wifi_password = st.text_input(
|
|
"Password",
|
|
type="password",
|
|
placeholder="Enter WiFi password",
|
|
help="Leave empty for open networks"
|
|
)
|
|
|
|
wifi_hidden = st.checkbox(
|
|
"Hidden Network",
|
|
value=False,
|
|
help="Check if this is a hidden network"
|
|
)
|
|
|
|
# Map security display to QR code format
|
|
security_map = {
|
|
"WPA/WPA2": "WPA",
|
|
"WEP": "WEP",
|
|
"None (Open)": "nopass"
|
|
}
|
|
|
|
# Generate WiFi QR string
|
|
if wifi_ssid:
|
|
wifi_qr = WiFiQRCode(
|
|
ssid=wifi_ssid,
|
|
password=wifi_password if wifi_security != "None (Open)" else "",
|
|
security=security_map[wifi_security],
|
|
hidden=wifi_hidden
|
|
)
|
|
qr_content = wifi_qr.to_string()
|
|
else:
|
|
qr_content = ""
|
|
|
|
# Logo upload (optional)
|
|
st.subheader("Logo (Optional)")
|
|
logo_file = st.file_uploader(
|
|
"Upload logo image",
|
|
type=["png", "jpg", "jpeg"],
|
|
help="Upload a logo to place in the center of the QR code"
|
|
)
|
|
|
|
if logo_file:
|
|
logo_size_ratio = st.slider(
|
|
"Logo Size",
|
|
min_value=0.1,
|
|
max_value=0.4,
|
|
value=0.3,
|
|
step=0.05,
|
|
help="Logo size as ratio of QR code size"
|
|
)
|
|
|
|
# Generate button
|
|
if st.button("Generate QR Code", type="primary", use_container_width=True):
|
|
if not qr_content:
|
|
if qr_mode == "URL":
|
|
st.error("Please enter a URL")
|
|
else:
|
|
st.error("Please enter WiFi network name (SSID)")
|
|
return
|
|
|
|
try:
|
|
with st.spinner("Generating QR code..."):
|
|
# Initialize generator
|
|
generator = QRCodeGenerator(qr_content, error_level)
|
|
|
|
# Generate QR code
|
|
if export_format == "SVG":
|
|
# Generate SVG directly
|
|
svg_data = generator.generate_svg(scale=svg_scale)
|
|
|
|
# Display preview (SVG as image)
|
|
st.success("QR Code generated successfully!")
|
|
st.image(svg_data, caption="QR Code Preview")
|
|
|
|
# Download button
|
|
file_prefix = "wifi_qr" if qr_mode == "WiFi" else "url_qr"
|
|
st.download_button(
|
|
label=f"Download QR Code (SVG)",
|
|
data=svg_data,
|
|
file_name=f"{file_prefix}.svg",
|
|
mime="image/svg+xml",
|
|
use_container_width=True
|
|
)
|
|
else:
|
|
# Generate raster image (PNG/JPEG)
|
|
qr_image = generator.generate_qr_image(
|
|
box_size=20,
|
|
border=4,
|
|
fill_color=fill_color,
|
|
back_color=back_color
|
|
)
|
|
|
|
# Add logo if provided
|
|
if logo_file:
|
|
logo_image = Image.open(logo_file)
|
|
qr_image = generator.add_logo(
|
|
qr_image,
|
|
logo_image,
|
|
logo_size_ratio
|
|
)
|
|
|
|
# Resize to target resolution
|
|
qr_image = generator.resize_image(
|
|
qr_image,
|
|
(target_size, target_size)
|
|
)
|
|
|
|
# Export image
|
|
image_data = generator.export_image(
|
|
qr_image,
|
|
format=export_format,
|
|
quality=95
|
|
)
|
|
|
|
# Display preview
|
|
st.success("QR Code generated successfully!")
|
|
st.image(qr_image, caption="QR Code Preview")
|
|
|
|
# Download button
|
|
mime_types = {
|
|
"PNG": "image/png",
|
|
"JPEG": "image/jpeg"
|
|
}
|
|
|
|
file_prefix = "wifi_qr" if qr_mode == "WiFi" else "url_qr"
|
|
st.download_button(
|
|
label=f"Download QR Code ({export_format}, {target_size}px)",
|
|
data=image_data,
|
|
file_name=f"{file_prefix}.{export_format.lower()}",
|
|
mime=mime_types[export_format],
|
|
use_container_width=True
|
|
)
|
|
|
|
# Display QR code info
|
|
with st.expander("QR Code Information"):
|
|
st.write(f"**Type:** {qr_mode}")
|
|
if qr_mode == "URL":
|
|
st.write(f"**URL:** {qr_content}")
|
|
else:
|
|
st.write(f"**Network:** {wifi_ssid}")
|
|
st.write(f"**Security:** {wifi_security}")
|
|
st.write(f"**Hidden:** {'Yes' if wifi_hidden else 'No'}")
|
|
st.write(f"**Error Correction:** {error_correction}")
|
|
st.write(f"**Format:** {export_format}")
|
|
if export_format in ["PNG", "JPEG"]:
|
|
st.write(f"**Resolution:** {target_size}x{target_size}px")
|
|
st.write(f"**Logo:** {'Yes' if logo_file else 'No'}")
|
|
|
|
except Exception as e:
|
|
st.error(f"Error generating QR code: {str(e)}")
|
|
st.exception(e)
|
|
|
|
# Footer
|
|
st.divider()
|
|
st.markdown(
|
|
"""
|
|
<div style='text-align: center; color: gray; font-size: 0.9em;'>
|
|
<p>Built with Streamlit | QR Code Generator v1.0</p>
|
|
<p>Tip: Use high error correction (H) when adding logos</p>
|
|
</div>
|
|
""",
|
|
unsafe_allow_html=True
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|