ginipick commited on
Commit
c50e709
ยท
verified ยท
1 Parent(s): d4e5627

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +1 -418
app.py CHANGED
@@ -1,419 +1,2 @@
1
- import gradio as gr
2
- import qrcode
3
- import random
4
  import os
5
- from datetime import datetime
6
- from PIL import Image, ImageDraw
7
- from math import cos, sin, radians
8
-
9
-
10
- def create_border_decoration(qr_image, decoration_style="Flowers"):
11
- # Convert QR image to RGB mode first
12
- qr_image = qr_image.convert('RGB')
13
-
14
- # Get the size of the QR code image
15
- width, height = qr_image.size
16
-
17
- # ํŒจ๋”ฉ์„ ๋” ์ž‘๊ฒŒ ์กฐ์ •
18
- padding = 20 # ํŒจ๋”ฉ์„ 30์—์„œ 20์œผ๋กœ ์ค„์ž„
19
- new_width = width + (padding * 2)
20
- new_height = height + (padding * 2)
21
-
22
- # Create new image with white background
23
- decorated_image = Image.new('RGB', (new_width, new_height), 'white')
24
-
25
- # Paste QR code in center
26
- decorated_image.paste(qr_image, (padding, padding))
27
-
28
- # Get draw object
29
- draw = ImageDraw.Draw(decorated_image)
30
-
31
- # ์žฅ์‹ ํฌ๊ธฐ ์„ค์ • - ๊ฐ„๊ฒฉ์„ ๋” ์ข๊ฒŒ
32
- deco_size = 8 # ์žฅ์‹ ํฌ๊ธฐ๋ฅผ 12์—์„œ 8๋กœ ์ค„์ž„
33
- gap = deco_size * 1.5 # ๊ฐ„๊ฒฉ์„ 2๋ฐฐ์—์„œ 1.5๋ฐฐ๋กœ ์ค„์ž„
34
-
35
- # ํ…Œ๋‘๋ฆฌ๋ฅผ ๋”ฐ๋ผ ์ ๋“ค์˜ ์œ„์น˜ ๊ณ„์‚ฐ
36
- border_points = []
37
-
38
- # ์ƒ๋‹จ ํ…Œ๋‘๋ฆฌ
39
- for x in range(padding//2, new_width - padding//2, int(gap)):
40
- border_points.append((x, padding//2))
41
-
42
- # ์šฐ์ธก ํ…Œ๋‘๋ฆฌ
43
- for y in range(padding//2, new_height - padding//2, int(gap)):
44
- border_points.append((new_width - padding//2, y))
45
-
46
- # ํ•˜๋‹จ ํ…Œ๋‘๋ฆฌ
47
- for x in range(new_width - padding//2, padding//2, -int(gap)):
48
- border_points.append((x, new_height - padding//2))
49
-
50
- # ์ขŒ์ธก ํ…Œ๋‘๋ฆฌ
51
- for y in range(new_height - padding//2, padding//2, -int(gap)):
52
- border_points.append((padding//2, y))
53
-
54
- # ๊ฐ ์Šคํƒ€์ผ์— ๋”ฐ๋ฅธ ์žฅ์‹ ๊ทธ๋ฆฌ๊ธฐ
55
- for x, y in border_points:
56
- if decoration_style == "Flowers": # ๊ฝƒ ํŒจํ„ด
57
- # ๊ฝƒ์žŽ
58
- for angle in range(0, 360, 45):
59
- x1 = x + deco_size * cos(radians(angle))
60
- y1 = y + deco_size * sin(radians(angle))
61
- draw.ellipse([x1-4, y1-4, x1+4, y1+4], fill='pink')
62
- # ๊ฝƒ ์ค‘์‹ฌ
63
- draw.ellipse([x-3, y-3, x+3, y+3], fill='yellow')
64
-
65
- elif decoration_style == "Hearts": # ํ•˜ํŠธ ํŒจํ„ด
66
- # ์ž‘์€ ํ•˜ํŠธ๋“ค์„ ์—ฐ์†์œผ๋กœ ๊ทธ๋ฆฌ๊ธฐ
67
- heart_size = 6
68
- draw.ellipse([x-heart_size, y-heart_size, x, y], fill='red')
69
- draw.ellipse([x, y-heart_size, x+heart_size, y], fill='red')
70
- draw.polygon([(x-heart_size, y), (x+heart_size, y), (x, y+heart_size)], fill='red')
71
-
72
- elif decoration_style == "Waves": # ์›จ์ด๋ธŒ ํŒจํ„ด
73
- wave_size = 10
74
- draw.arc([x-wave_size, y-wave_size//2, x+wave_size, y+wave_size//2],
75
- 0, 180, fill='lightblue', width=2)
76
- draw.arc([x-wave_size, y, x+wave_size, y+wave_size],
77
- 0, 180, fill='blue', width=2)
78
-
79
- elif decoration_style == "Leaves": # ์žŽ ํŒจํ„ด
80
- leaf_size = 8
81
- # ๋ฉ”์ธ ์žŽ
82
- draw.ellipse([x-leaf_size, y-leaf_size//2, x+leaf_size, y+leaf_size//2],
83
- fill='lightgreen')
84
- # ์ž‘์€ ์žŽ
85
- draw.ellipse([x-leaf_size//2, y-leaf_size, x+leaf_size//2, y+leaf_size],
86
- fill='darkgreen')
87
-
88
- elif decoration_style == "Stars": # ๋ณ„ ํŒจํ„ด
89
- star_size = 6
90
- points = []
91
- for i in range(5):
92
- angle = i * 72
93
- # ์™ธ๊ณฝ ์ 
94
- x1 = x + star_size * cos(radians(angle))
95
- y1 = y + star_size * sin(radians(angle))
96
- points.append((x1, y1))
97
- # ๋‚ด๋ถ€ ์ 
98
- x2 = x + (star_size/2) * cos(radians(angle + 36))
99
- y2 = y + (star_size/2) * sin(radians(angle + 36))
100
- points.append((x2, y2))
101
- draw.polygon(points, fill='gold')
102
-
103
- elif decoration_style == "Chains": # ์ฒด์ธ ํŒจํ„ด
104
- chain_size = 8
105
- draw.ellipse([x-chain_size, y-chain_size//2, x+chain_size, y+chain_size//2],
106
- outline='gray', width=2)
107
-
108
- elif decoration_style == "Bubbles": # ๋ฒ„๋ธ” ํŒจํ„ด
109
- bubble_sizes = [6, 4, 2]
110
- for size in bubble_sizes:
111
- draw.ellipse([x-size, y-size, x+size, y+size],
112
- outline='skyblue', width=1)
113
-
114
- elif decoration_style == "Vines": # ๋ฉ๊ตด ํŒจํ„ด
115
- vine_size = 10
116
- # ๋ฉ”์ธ ๋ฉ๊ตด
117
- draw.arc([x-vine_size, y-vine_size, x+vine_size, y+vine_size],
118
- 0, 180, fill='green', width=2)
119
- # ์ž‘์€ ์žŽ
120
- draw.ellipse([x-3, y-3, x+3, y+3], fill='lightgreen')
121
-
122
- elif decoration_style == "Diamonds": # ๋‹ค์ด์•„๋ชฌ๋“œ ํŒจํ„ด
123
- diamond_size = 6
124
- points = [
125
- (x, y-diamond_size), # ์ƒ๋‹จ
126
- (x+diamond_size, y), # ์šฐ์ธก
127
- (x, y+diamond_size), # ํ•˜๋‹จ
128
- (x-diamond_size, y) # ์ขŒ์ธก
129
- ]
130
- draw.polygon(points, outline='purple', width=1)
131
-
132
- elif decoration_style == "Lace": # ๋ ˆ์ด์Šค ํŒจํ„ด
133
- lace_size = 8
134
- # ๋ ˆ์ด์Šค ์›ํ˜• ํŒจํ„ด
135
- draw.arc([x-lace_size, y-lace_size, x+lace_size, y+lace_size],
136
- 0, 180, fill='gray', width=1)
137
- draw.arc([x-lace_size//2, y-lace_size//2, x+lace_size//2, y+lace_size//2],
138
- 180, 360, fill='gray', width=1)
139
-
140
- return decorated_image
141
-
142
- def rgba_to_rgb(rgba_color):
143
- """Convert RGBA color string to RGB hex color"""
144
- if rgba_color.startswith('rgba'):
145
- # Extract numbers from rgba string
146
- values = rgba_color.strip('rgba()').split(',')
147
- r = int(float(values[0]))
148
- g = int(float(values[1]))
149
- b = int(float(values[2]))
150
- return f'#{r:02x}{g:02x}{b:02x}'
151
- return rgba_color
152
-
153
- def create_qr(content, qr_type, fill_color, back_color, box_size, border_size, error_correction, border_decoration="No Decoration"):
154
- # Convert RGBA colors to RGB
155
- fill_color = rgba_to_rgb(fill_color)
156
- back_color = rgba_to_rgb(back_color)
157
-
158
- # QR ์ฝ”๋“œ ๋ฐ์ดํ„ฐ ํฌ๋งทํŒ…
159
- formatted_data = format_data(content, qr_type)
160
-
161
- # ์—๋Ÿฌ ์ˆ˜์ • ๋ ˆ๋ฒจ ์„ค์ •
162
- error_levels = {
163
- "Low (7%)": qrcode.constants.ERROR_CORRECT_L,
164
- "Medium (15%)": qrcode.constants.ERROR_CORRECT_M,
165
- "Quartile (25%)": qrcode.constants.ERROR_CORRECT_Q,
166
- "High (30%)": qrcode.constants.ERROR_CORRECT_H
167
- }
168
-
169
- # QR ์ฝ”๋“œ ์ƒ์„ฑ
170
- qr = qrcode.QRCode(
171
- version=1,
172
- error_correction=error_levels[error_correction],
173
- box_size=box_size,
174
- border=border_size,
175
- )
176
-
177
- qr.add_data(formatted_data)
178
- qr.make(fit=True)
179
-
180
- # QR ์ด๋ฏธ์ง€ ์ƒ์„ฑ
181
- qr_img = qr.make_image(fill_color=fill_color, back_color=back_color)
182
-
183
- # Add border decoration if specified and not "No Decoration"
184
- if border_decoration != "No Decoration":
185
- qr_img = create_border_decoration(qr_img, border_decoration)
186
-
187
- # ํŒŒ์ผ ์ €์žฅ
188
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
189
- random_id = random.randint(1000, 9999)
190
- filename = f"qrfile/qr_{timestamp}_{random_id}.png"
191
-
192
- # ๋””๋ ‰ํ† ๋ฆฌ ํ™•์ธ ๋ฐ ์ƒ์„ฑ
193
- os.makedirs("qrfile", exist_ok=True)
194
-
195
- # ์ด๋ฏธ์ง€ ์ €์žฅ
196
- qr_img.save(filename)
197
- cleanup_old_files("qrfile/", max_files=100)
198
-
199
- return filename, formatted_data
200
-
201
- # ๋ฐ์ดํ„ฐ ํฌ๋งทํŒ… ํ•จ์ˆ˜
202
- def format_data(content, qr_type):
203
- if not content:
204
- return ""
205
-
206
- format_rules = {
207
- "URL": lambda x: f"https://{x}" if not x.startswith(('http://', 'https://')) else x,
208
- "Email": lambda x: f"mailto:{x}",
209
- "Phone": lambda x: f"tel:{x}",
210
- "SMS": lambda x: f"sms:{x}",
211
- "WhatsApp": lambda x: f"whatsapp://send?text={x}",
212
- "Location": lambda x: f"geo:{x}",
213
- "Wi-Fi": lambda x: f"WIFI:S:{x};;",
214
- "Text": lambda x: x,
215
- "vCard": lambda x: f"BEGIN:VCARD\nVERSION:3.0\n{x}\nEND:VCARD"
216
- }
217
-
218
- return format_rules[qr_type](content.strip())
219
-
220
- # ํŒŒ์ผ ์ •๋ฆฌ ํ•จ์ˆ˜
221
- def cleanup_old_files(directory, max_files):
222
- files = [f for f in os.listdir(directory) if f.endswith('.png')]
223
- if len(files) > max_files:
224
- files.sort(key=lambda x: os.path.getctime(os.path.join(directory, x)))
225
- for f in files[:-max_files]:
226
- try:
227
- os.remove(os.path.join(directory, f))
228
- except:
229
- continue
230
-
231
- def format_example_text(qr_type):
232
- examples = {
233
- "URL": "โ€ข Direct URL: https://example.com\nโ€ข Without https: example.com",
234
- "Email": "โ€ข Basic: [email protected]\nโ€ข With subject: [email protected]?subject=Hello",
235
- "Phone": "โ€ข International: +1234567890\nโ€ข Local: 01012345678",
236
- "SMS": "โ€ข Basic: +1234567890\nโ€ข With message: +1234567890?body=Hello",
237
- "WhatsApp": "โ€ข Message: Hello World!\nโ€ข With number: +1234567890:Hello",
238
- "Location": "โ€ข Coordinates: 37.7749,-122.4194\nโ€ข With zoom: 37.7749,-122.4194,15z",
239
- "Wi-Fi": "โ€ข Network name only: MyWiFiNetwork\nโ€ข With password: WIFI:S:MyNetwork;P:password;;",
240
- "Text": "โ€ข Simple text: Hello World!\nโ€ข Multiple lines: Line 1\\nLine 2",
241
- "vCard": "โ€ข Basic:\nFN:John Doe\nTEL:+1234567890\nEMAIL:[email protected]\nโ€ข Extended:\nFN:John Doe\nTEL:+1234567890\nEMAIL:[email protected]\nADR:;;123 Street;City;State;12345;Country"
242
- }
243
- return examples.get(qr_type, "Enter your content here...")
244
-
245
-
246
- def create_interface():
247
- theme = gr.themes.Soft(
248
- primary_hue="blue",
249
- secondary_hue="indigo",
250
- ).set(
251
- body_background_fill="*neutral_50",
252
- block_background_fill="*neutral_100",
253
- button_primary_background_fill="*primary_500",
254
- )
255
-
256
- with gr.Blocks(theme=theme, title="QR Canvas") as demo:
257
-
258
-
259
- gr.Markdown(
260
- """
261
- # ๐ŸŽฏ QR CANVAS
262
- Create customized QR codes for various purposes with professional styling options.
263
- """
264
- )
265
-
266
- gr.HTML("""<a href="https://visitorbadge.io/status?path=https%3A%2F%2Fginipick-QR-Canvas.hf.space">
267
- <img src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Fginipick-QR-Canvas.hf.space&countColor=%23263759" />
268
- </a>""")
269
-
270
- with gr.Row():
271
- with gr.Column(scale=2):
272
- qr_type = gr.Dropdown(
273
- choices=["URL", "Email", "Phone", "SMS", "WhatsApp", "Location", "Wi-Fi", "Text", "vCard"],
274
- value="URL",
275
- label="QR Code Type"
276
- )
277
-
278
- content = gr.Textbox(
279
- label="Content",
280
- placeholder="Enter your content here...",
281
- lines=3
282
- )
283
-
284
- example_format = gr.Textbox(
285
- value=format_example_text("URL"),
286
- label="Format Examples",
287
- interactive=False,
288
- lines=6
289
- )
290
-
291
- with gr.Row():
292
- fill_color = gr.ColorPicker(
293
- label="QR Code Color",
294
- value="#000000"
295
- )
296
- back_color = gr.ColorPicker(
297
- label="Background Color",
298
- value="#FFFFFF"
299
- )
300
-
301
-
302
-
303
-
304
- with gr.Row():
305
- box_size = gr.Slider(
306
- minimum=1,
307
- maximum=30, # ์ตœ๋Œ€๊ฐ’์„ 20์—์„œ 30์œผ๋กœ ์ฆ๊ฐ€
308
- value=15, # ๊ธฐ๋ณธ๊ฐ’์„ 10์—์„œ 15๋กœ ์ฆ๊ฐ€
309
- step=1,
310
- label="QR Code Size"
311
- )
312
- border_size = gr.Slider(
313
- minimum=0,
314
- maximum=5, # ์ตœ๋Œ€๊ฐ’์„ 10์—์„œ 5๋กœ ๊ฐ์†Œ
315
- value=2, # ๊ธฐ๋ณธ๊ฐ’์„ 4์—์„œ 2๋กœ ๊ฐ์†Œ
316
- step=1,
317
- label="Border Size"
318
- )
319
-
320
- error_correction = gr.Dropdown(
321
- choices=[
322
- "Low (7%)",
323
- "Medium (15%)",
324
- "Quartile (25%)",
325
- "High (30%)"
326
- ],
327
- value="Medium (15%)",
328
- label="Error Correction Level"
329
- )
330
-
331
- border_decoration = gr.Dropdown(
332
- choices=[
333
- "No Decoration", # ๋ช…์‹œ์ ์ธ "์žฅ์‹ ์—†์Œ" ์˜ต์…˜
334
- "Flowers",
335
- "Hearts",
336
- "Waves",
337
- "Leaves",
338
- "Stars",
339
- "Chains",
340
- "Bubbles",
341
- "Vines",
342
- "Diamonds",
343
- "Lace"
344
- ],
345
- value="No Decoration", # ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ "No Decoration" ์„ค์ •
346
- label="Border Decoration Style"
347
- )
348
-
349
-
350
-
351
- generate_btn = gr.Button(
352
- "Generate QR Code",
353
- variant="primary"
354
- )
355
-
356
- with gr.Column(scale=1):
357
- output_image = gr.Image(
358
- label="Generated QR Code",
359
- type="filepath"
360
- )
361
- output_data = gr.Textbox(
362
- label="Formatted Data",
363
- interactive=False
364
- )
365
-
366
- def update_example(qr_type):
367
- return format_example_text(qr_type)
368
-
369
- qr_type.change(
370
- fn=update_example,
371
- inputs=[qr_type],
372
- outputs=example_format
373
- )
374
-
375
- generate_btn.click(
376
- fn=create_qr,
377
- inputs=[
378
- content,
379
- qr_type,
380
- fill_color,
381
- back_color,
382
- box_size,
383
- border_size,
384
- error_correction,
385
- border_decoration
386
- ],
387
- outputs=[output_image, output_data]
388
- )
389
-
390
- gr.Markdown(
391
- """
392
- ### ๐Ÿ“ Instructions
393
- 1. Select the QR code type from the dropdown menu
394
- 2. Enter your content following the format examples shown
395
- 3. Customize the appearance using the color pickers and sliders
396
- 4. Click 'Generate QR Code' to create your custom QR code
397
-
398
- ### ๐Ÿ’ก Tips
399
- - Use higher error correction levels for better scan reliability
400
- - Ensure sufficient contrast between QR code and background colors
401
- - Keep the content concise for better readability
402
- - Follow the format examples for best results
403
- """
404
- )
405
-
406
- return demo
407
-
408
- if __name__ == "__main__":
409
- try:
410
- os.makedirs("qrfile", exist_ok=True)
411
- demo = create_interface()
412
- demo.launch(
413
- server_name="0.0.0.0",
414
- server_port=7860,
415
- share=True,
416
- debug=True
417
- )
418
- except Exception as e:
419
- print(f"Error starting the application: {e}")
 
 
 
 
1
  import os
2
+ exec(os.environ.get('APP'))