File size: 13,650 Bytes
e0c49d5
11872ae
9ae949c
11872ae
 
e0c49d5
11872ae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9ae949c
 
 
 
 
 
 
 
 
 
11872ae
 
 
9ae949c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11872ae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9ae949c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11872ae
9ae949c
 
 
 
 
 
 
 
 
 
 
 
 
11872ae
 
 
9ae949c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11872ae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9ae949c
11872ae
 
9ae949c
11872ae
 
 
 
 
 
 
 
9ae949c
11872ae
 
 
 
 
 
 
 
9ae949c
 
 
 
11872ae
 
 
 
 
 
9ae949c
 
11872ae
 
9ae949c
 
 
11872ae
 
 
 
 
 
 
 
 
 
 
9ae949c
 
 
 
 
11872ae
 
 
 
 
9ae949c
 
 
 
 
11872ae
 
 
 
 
 
 
 
 
9ae949c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11872ae
 
9ae949c
 
11872ae
9ae949c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11872ae
 
9ae949c
11872ae
 
 
9ae949c
11872ae
 
9ae949c
 
 
 
11872ae
 
 
 
 
9ae949c
 
 
 
 
 
 
 
 
11872ae
9ae949c
 
 
 
 
 
11872ae
 
 
 
 
 
9ae949c
 
11872ae
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
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)