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'))