qr-python / src /streamlit_app.py
sameernotes's picture
Update src/streamlit_app.py
9ae949c verified
import streamlit as st
import qrcode
from PIL import Image, ImageDraw, ImageFont
import io
import base64
# Page configuration
st.set_page_config(
page_title="QR Code Generator",
page_icon="πŸ“±",
layout="wide",
initial_sidebar_state="expanded"
)
# Custom CSS for beautiful styling
st.markdown("""
<style>
.main-header {
text-align: center;
padding: 2rem 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 10px;
margin-bottom: 2rem;
}
.feature-box {
background: #f8f9fa;
padding: 1.5rem;
border-radius: 10px;
border-left: 4px solid #667eea;
margin: 1rem 0;
}
.download-section {
background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);
padding: 2rem;
border-radius: 15px;
text-align: center;
margin: 2rem 0;
}
.sidebar-section {
background: #ffffff;
padding: 1rem;
border-radius: 10px;
margin: 1rem 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.stDownloadButton > button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 10px;
padding: 0.5rem 2rem;
font-weight: bold;
width: 100%;
}
</style>
""", unsafe_allow_html=True)
def hex_to_rgb(hex_color):
"""Convert hex color to RGB tuple"""
hex_color = hex_color.lstrip('#')
return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
def create_gradient_image(size, start_color, end_color, direction='horizontal'):
"""Create a gradient image"""
image = Image.new('RGB', size)
draw = ImageDraw.Draw(image)
if direction == 'horizontal':
for x in range(size[0]):
ratio = x / size[0]
r = int(start_color[0] * (1 - ratio) + end_color[0] * ratio)
g = int(start_color[1] * (1 - ratio) + end_color[1] * ratio)
b = int(start_color[2] * (1 - ratio) + end_color[2] * ratio)
draw.line([(x, 0), (x, size[1])], fill=(r, g, b))
else: # vertical
for y in range(size[1]):
ratio = y / size[1]
r = int(start_color[0] * (1 - ratio) + end_color[0] * ratio)
g = int(start_color[1] * (1 - ratio) + end_color[1] * ratio)
b = int(start_color[2] * (1 - ratio) + end_color[2] * ratio)
draw.line([(0, y), (size[0], y)], fill=(r, g, b))
return image
def create_rounded_qr(qr_img, corner_radius=20):
"""Create rounded corners for QR code"""
# Create mask for rounded corners
size = qr_img.size
mask = Image.new('L', size, 0)
draw = ImageDraw.Draw(mask)
draw.rounded_rectangle([(0, 0), size], corner_radius, fill=255)
# Apply mask
qr_rounded = Image.new('RGBA', size, (255, 255, 255, 0))
qr_rounded.paste(qr_img, (0, 0))
qr_rounded.putalpha(mask)
return qr_rounded
def create_qr_code(data, fill_color, back_color, border, box_size, error_correction, style_type, gradient_end_color=None):
"""Generate QR code with custom styling"""
# Error correction levels
error_levels = {
'L (~7%)': qrcode.constants.ERROR_CORRECT_L,
'M (~15%)': qrcode.constants.ERROR_CORRECT_M,
'Q (~25%)': qrcode.constants.ERROR_CORRECT_Q,
'H (~30%)': qrcode.constants.ERROR_CORRECT_H
}
# Create QR code instance
qr = qrcode.QRCode(
version=1,
error_correction=error_levels[error_correction],
box_size=box_size,
border=border,
)
qr.add_data(data)
qr.make(fit=True)
# Generate base QR code
if style_type == "Gradient" and gradient_end_color:
# Create gradient background
img = qr.make_image(fill_color='black', back_color='white')
# Create gradient
start_rgb = hex_to_rgb(fill_color)
end_rgb = hex_to_rgb(gradient_end_color)
gradient = create_gradient_image(img.size, start_rgb, end_rgb, 'horizontal')
# Apply gradient to QR code
img_array = img.load()
gradient_array = gradient.load()
for x in range(img.size[0]):
for y in range(img.size[1]):
if img_array[x, y] == 0: # Black pixel (QR code data)
img_array[x, y] = gradient_array[x, y]
else: # White pixel (background)
img_array[x, y] = hex_to_rgb(back_color)
else:
img = qr.make_image(fill_color=fill_color, back_color=back_color)
# Apply style modifications
if style_type == "Rounded":
img = create_rounded_qr(img, corner_radius=box_size*2)
elif style_type == "With Logo Space":
# Create space in center for logo
draw = ImageDraw.Draw(img)
center_x, center_y = img.size[0] // 2, img.size[1] // 2
logo_size = min(img.size) // 6
draw.rectangle([
center_x - logo_size//2, center_y - logo_size//2,
center_x + logo_size//2, center_y + logo_size//2
], fill=back_color, outline=fill_color, width=2)
return img
def get_qr_data_by_type(content_type):
"""Get QR data based on content type"""
if content_type == "Text":
return st.text_area("Enter your text:", height=100, placeholder="Hello World!")
elif content_type == "URL":
url = st.text_input("Enter URL:", placeholder="https://example.com")
if url and not url.startswith(('http://', 'https://')):
url = 'https://' + url
return url
elif content_type == "Email":
email = st.text_input("Email address:", placeholder="contact@example.com")
subject = st.text_input("Subject (optional):")
body = st.text_area("Message (optional):", height=80)
if email:
params = []
if subject:
params.append(f"subject={subject}")
if body:
params.append(f"body={body}")
return f"mailto:{email}{'?' + '&'.join(params) if params else ''}"
return ""
elif content_type == "Phone":
phone = st.text_input("Phone number:", placeholder="+1234567890")
return f"tel:{phone}" if phone else ""
elif content_type == "SMS":
phone = st.text_input("Phone number:", placeholder="+1234567890")
message = st.text_area("Message:", height=80, placeholder="Hello!")
if phone:
return f"sms:{phone}{'?body=' + message if message else ''}"
return ""
elif content_type == "WiFi":
ssid = st.text_input("Network Name (SSID):", placeholder="MyWiFi")
password = st.text_input("Password:", type="password")
security = st.selectbox("Security Type", ["WPA", "WEP", "nopass"])
hidden = st.checkbox("Hidden Network")
if ssid:
return f"WIFI:T:{security};S:{ssid};P:{password};H:{'true' if hidden else 'false'};;"
return ""
elif content_type == "vCard":
name = st.text_input("Full Name:", placeholder="John Doe")
phone = st.text_input("Phone:", placeholder="+1234567890")
email = st.text_input("Email:", placeholder="john@example.com")
organization = st.text_input("Organization (optional):", placeholder="Company Inc.")
if name:
vcard = f"BEGIN:VCARD\nVERSION:3.0\nFN:{name}\n"
if phone:
vcard += f"TEL:{phone}\n"
if email:
vcard += f"EMAIL:{email}\n"
if organization:
vcard += f"ORG:{organization}\n"
vcard += "END:VCARD"
return vcard
return ""
# Main header
st.markdown("""
<div class="main-header">
<h1>🎨 Beautiful QR Code Generator</h1>
<p>Create stunning, customizable QR codes with advanced styling options</p>
</div>
""", unsafe_allow_html=True)
# Sidebar for customization
with st.sidebar:
st.markdown("## πŸŽ›οΈ Customization Panel")
# QR Code Content
st.markdown('<div class="sidebar-section">', unsafe_allow_html=True)
st.markdown("### πŸ“ Content")
content_type = st.selectbox(
"Content Type",
["Text", "URL", "Email", "Phone", "SMS", "WiFi", "vCard"]
)
qr_data = get_qr_data_by_type(content_type)
st.markdown('</div>', unsafe_allow_html=True)
# Style Settings
st.markdown('<div class="sidebar-section">', unsafe_allow_html=True)
st.markdown("### 🎨 Style Settings")
style_type = st.selectbox(
"QR Style",
["Standard", "Rounded", "Gradient", "With Logo Space"]
)
col1, col2 = st.columns(2)
with col1:
fill_color = st.color_picker("Foreground Color", "#000000")
with col2:
back_color = st.color_picker("Background Color", "#FFFFFF")
gradient_end_color = None
if style_type == "Gradient":
gradient_end_color = st.color_picker("Gradient End Color", "#333333")
st.markdown('</div>', unsafe_allow_html=True)
# Advanced Settings
st.markdown('<div class="sidebar-section">', unsafe_allow_html=True)
st.markdown("### βš™οΈ Advanced Settings")
box_size = st.slider("Module Size", 5, 20, 10, help="Size of each QR code square")
border = st.slider("Border Width", 1, 10, 4, help="White border around QR code")
error_correction = st.selectbox(
"Error Correction Level",
["L (~7%)", "M (~15%)", "Q (~25%)", "H (~30%)"],
index=1,
help="Higher levels = more damage resistance but larger code"
)
st.markdown('</div>', unsafe_allow_html=True)
# Main content area
col1, col2 = st.columns([2, 1])
with col1:
if qr_data:
try:
# Generate QR code
with st.spinner("🎨 Generating your beautiful QR code..."):
qr_img = create_qr_code(
qr_data, fill_color, back_color, border,
box_size, error_correction, style_type, gradient_end_color
)
# Display QR code
st.markdown("### πŸ“± Your QR Code")
st.image(qr_img, caption="Generated QR Code", use_container_width=True)
# Convert to bytes for download
img_buffer = io.BytesIO()
qr_img.save(img_buffer, format="PNG")
img_bytes = img_buffer.getvalue()
# Download section
st.markdown("""
<div class="download-section">
<h3>πŸš€ Ready to Download!</h3>
<p>Your QR code is ready. Click below to download it as PNG.</p>
</div>
""", unsafe_allow_html=True)
# Download button
filename = f"qrcode_{content_type.lower()}_{style_type.lower().replace(' ', '_')}.png"
st.download_button(
label="πŸ“₯ Download QR Code",
data=img_bytes,
file_name=filename,
mime="image/png",
use_container_width=True
)
# QR Code Info
st.info(f"""
**QR Code Details:**
- Content Type: {content_type}
- Style: {style_type}
- Size: {qr_img.size[0]}x{qr_img.size[1]} pixels
- Error Correction: {error_correction}
""")
except Exception as e:
st.error(f"❌ Error generating QR code: {str(e)}")
st.info("πŸ’‘ Try adjusting your content or settings")
else:
# Welcome message with example
st.markdown("""
### πŸ‘‹ Welcome to QR Code Generator!
πŸ‘ˆ **Get started by entering content in the sidebar**
#### 🌟 What you can create:
- **Text QR codes** for messages
- **URL QR codes** for websites
- **Contact QR codes** (vCard format)
- **WiFi QR codes** for easy connection
- **Email & SMS QR codes**
#### 🎨 Styling options:
- Custom colors
- Rounded corners
- Gradient effects
- Logo space preparation
""")
with col2:
st.markdown("### ✨ Features")
features = [
"🎨 Multiple visual styles",
"🌈 Custom colors & gradients",
"πŸ“± Various content types",
"βš™οΈ Advanced settings",
"πŸ“₯ Instant PNG download",
"πŸ”§ Error correction levels",
"πŸ“‡ vCard contact support",
"πŸ“Ά WiFi QR codes"
]
for feature in features:
st.markdown(f'<div class="feature-box">{feature}</div>', unsafe_allow_html=True)
st.markdown("### πŸ’‘ Pro Tips")
st.success("""
**🎯 Best Practices:**
- Use high contrast colors
- Test with your phone camera
- Higher error correction for outdoor use
- Larger module size for distant scanning
- Keep URLs short for simpler codes
""")
st.markdown("### πŸ“Š Error Correction Guide")
st.info("""
- **L (7%)**: Good for clean environments
- **M (15%)**: Standard recommendation
- **Q (25%)**: Better for rough handling
- **H (30%)**: Best for outdoor/damaged codes
""")
# Footer
st.markdown("---")
st.markdown("""
<div style="text-align: center; color: #666; padding: 2rem;">
<p>πŸš€ Built with Streamlit | πŸ’ Made for QR code enthusiasts</p>
<p><small>πŸ’‘ Tip: Bookmark this page for quick QR code generation!</small></p>
</div>
""", unsafe_allow_html=True)