ginipick commited on
Commit
6fd87e6
ยท
verified ยท
1 Parent(s): 918c0b1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +168 -147
app.py CHANGED
@@ -111,105 +111,100 @@ def process_images(image_paths, session_id):
111
  thumb_path = os.path.join(thumbs_folder, f"thumb_{i + 1}.png")
112
  create_thumbnail(img_path, thumb_path)
113
 
114
- # Add interactive content to specific pages as examples
115
  html_content = ""
116
- items = []
117
 
118
  if i == 0: # First image example with HTML content
119
  html_content = """
120
  <div style="position: absolute; top: 50px; left: 50px; background-color: rgba(255,255,255,0.7); padding: 10px; border-radius: 5px;">
121
- <h2 style="color: #333;">Image Gallery</h2>
122
- <p style="color: #666;">This is the first image in your gallery.</p>
123
- <a href="#" data-page="2" style="color: blue; text-decoration: underline;">Next Image</a>
 
 
 
 
 
 
124
  </div>
125
  """
126
- elif i == 1: # Second image with video example (if available)
127
- items = [
128
- {
129
- "type": "link",
130
- "x": 50,
131
- "y": 50,
132
- "width": 200,
133
- "height": 50,
134
- "page": 1,
135
- "title": "Previous image"
136
- }
137
- ]
138
-
139
- # Example of adding a YouTube video if it's the second image
140
- if len(image_paths) > 1:
141
- html_content = """
142
- <iframe class="flipbook-page-item"
143
- src="https://www.youtube.com/embed/dQw4w9WgXcQ"
144
- style="top:200px;left:50px;width:300px;height:200px;"
145
- frameborder="0"
146
- allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
147
- allowfullscreen="">
148
- </iframe>
149
- """
150
 
151
- # Add page info with interactive content
152
- pages_info.append({
153
- "src": os.path.join("output", session_id, f"image_{i + 1}.png"),
154
- "thumb": os.path.join("thumbs", session_id, f"thumb_{i + 1}.png"),
155
- "title": f"Image {i + 1}",
156
- "htmlContent": html_content if html_content else None,
157
- "items": items if items else None
158
- })
 
 
 
159
  except Exception as e:
160
  print(f"Error processing image {img_path}: {e}")
161
 
162
  return pages_info
163
 
164
- def create_flipbook_from_pdf(pdf_file, view_mode="webgl", skin="light"):
165
  """Create a flipbook from uploaded PDF."""
166
  try:
167
  session_id = str(uuid.uuid4())
168
  pages_info = []
 
169
 
170
  if pdf_file is not None:
171
  # In Gradio, pdf_file is a file path string, not the actual content
172
  pdf_path = pdf_file.name # Get the file path
 
173
 
174
  # Process PDF using the file path directly
175
  pages_info = process_pdf(pdf_path, session_id)
 
176
  else:
177
- return """<div style="color: red; padding: 20px;">Please upload a PDF file.</div>"""
178
 
179
  if not pages_info:
180
- return """<div style="color: red; padding: 20px;">Failed to process the uploaded PDF. Please try again.</div>"""
181
 
182
  # Create and return HTML for the flipbook
183
  flipbook_html = generate_flipbook_html(pages_info, session_id, view_mode, skin)
184
- return flipbook_html
 
185
 
186
  except Exception as e:
187
- print(f"Error creating flipbook from PDF: {e}")
188
- return f"""<div style="color: red; padding: 20px;">An error occurred: {str(e)}</div>"""
 
189
 
190
- def create_flipbook_from_images(images, view_mode="webgl", skin="light"):
191
  """Create a flipbook from uploaded images."""
192
  try:
193
  session_id = str(uuid.uuid4())
194
  pages_info = []
 
195
 
196
  if images is not None and len(images) > 0:
197
  # Process images using file paths
198
  image_paths = [img.name for img in images]
 
 
199
  pages_info = process_images(image_paths, session_id)
 
200
  else:
201
- return """<div style="color: red; padding: 20px;">Please upload at least one image.</div>"""
202
 
203
  if not pages_info:
204
- return """<div style="color: red; padding: 20px;">Failed to process the uploaded images. Please try again.</div>"""
205
 
206
  # Create and return HTML for the flipbook
207
  flipbook_html = generate_flipbook_html(pages_info, session_id, view_mode, skin)
208
- return flipbook_html
 
209
 
210
  except Exception as e:
211
- print(f"Error creating flipbook from images: {e}")
212
- return f"""<div style="color: red; padding: 20px;">An error occurred: {str(e)}</div>"""
 
213
 
214
  def generate_flipbook_html(pages_info, session_id, view_mode, skin):
215
  """Generate HTML for the flipbook."""
@@ -228,149 +223,175 @@ def generate_flipbook_html(pages_info, session_id, view_mode, skin):
228
 
229
  # HTML template with embedded CSS and JavaScript
230
  html = f"""
231
- <!DOCTYPE html>
232
- <html>
233
- <head>
234
- <meta charset="UTF-8">
235
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
236
- <title>3D Flipbook</title>
237
- <style>
238
- #flipbook-container {{
239
- width: 100%;
240
- height: 600px;
241
- margin: 0 auto;
242
- position: relative;
243
- }}
244
- body, html {{
245
- margin: 0;
246
- padding: 0;
247
- height: 100%;
248
- overflow: hidden;
249
- }}
250
- </style>
251
- <link rel="stylesheet" type="text/css" href="flipbook.css">
252
- </head>
253
- <body>
254
- <div id="{flipbook_id}" class="flipbook-container"></div>
255
-
256
- <script src="flipbook.js"></script>
257
- <script src="flipbook.webgl.js"></script>
258
- <script src="flipbook.swipe.js"></script>
259
- <script src="flipbook.scroll.js"></script>
260
- <script src="flipbook.book3.js"></script>
261
 
262
  <script>
263
- // Initialize flipbook when page loads
264
- document.addEventListener('DOMContentLoaded', function() {{
265
- const options = {{
266
- pages: {pages_json},
267
- viewMode: '{view_mode}',
268
- skin: '{skin}',
269
- responsiveView: true,
270
- singlePageMode: false,
271
- singlePageModeIfMobile: true,
272
- pageFlipDuration: 1,
273
- sound: true,
274
- backgroundMusic: false,
275
- thumbnailsOnStart: true,
276
- btnThumbs: {{ enabled: true }},
277
- btnPrint: {{ enabled: true }},
278
- btnDownloadPages: {{ enabled: true }},
279
- btnDownloadPdf: {{ enabled: true }},
280
- btnShare: {{ enabled: true }},
281
- btnSound: {{ enabled: true }},
282
- btnExpand: {{ enabled: true }},
283
- rightToLeft: false,
284
- autoplayOnStart: false,
285
- autoplayInterval: 3000
286
- }};
287
-
288
- const container = document.getElementById('{flipbook_id}');
289
- new FlipBook(container, options);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  }});
291
  </script>
292
- </body>
293
- </html>
 
 
 
 
 
 
 
294
  """
295
  return html
296
 
 
297
  with gr.Blocks(title="3D Flipbook Viewer") as demo:
298
  gr.Markdown("# 3D Flipbook Viewer")
299
  gr.Markdown("""
300
- ## Create interactive 3D flipbooks from PDFs or images
301
 
302
- Upload a PDF file or multiple images to generate an interactive flipbook with page-turning effects.
303
 
304
- ### Interactive Features:
305
- - The created flipbook includes interactive elements on the first pages
306
- - Navigate using the toolbar or by dragging page corners
307
- - Use the thumbnails view for quick navigation
308
- - Toggle fullscreen for better viewing experience
 
309
  """)
310
 
311
  with gr.Tabs():
312
- with gr.TabItem("PDF Upload"):
313
- pdf_file = gr.File(label="Upload PDF", file_types=[".pdf"])
314
 
315
- with gr.Accordion("Advanced Settings", open=False):
316
- pdf_view_mode = gr.Dropdown(
317
  choices=["webgl", "3d", "2d", "swipe"],
318
- value="webgl",
319
- label="View Mode"
 
320
  )
321
- pdf_skin = gr.Dropdown(
322
  choices=["light", "dark", "gradient"],
323
  value="light",
324
- label="Skin"
 
325
  )
326
 
327
- pdf_create_btn = gr.Button("Create Flipbook from PDF", variant="primary")
328
- pdf_output = gr.HTML(label="Flipbook Output")
 
329
 
330
  # Set up PDF event handler
331
  pdf_create_btn.click(
332
  fn=create_flipbook_from_pdf,
333
  inputs=[pdf_file, pdf_view_mode, pdf_skin],
334
- outputs=pdf_output
335
  )
336
 
337
- with gr.TabItem("Image Upload"):
338
- images = gr.File(label="Upload Images", file_types=["image"], file_count="multiple")
339
 
340
- with gr.Accordion("Advanced Settings", open=False):
341
- img_view_mode = gr.Dropdown(
342
  choices=["webgl", "3d", "2d", "swipe"],
343
- value="webgl",
344
- label="View Mode"
 
345
  )
346
- img_skin = gr.Dropdown(
347
  choices=["light", "dark", "gradient"],
348
  value="light",
349
- label="Skin"
 
350
  )
351
 
352
- img_create_btn = gr.Button("Create Flipbook from Images", variant="primary")
353
- img_output = gr.HTML(label="Flipbook Output")
 
354
 
355
  # Set up image event handler
356
  img_create_btn.click(
357
  fn=create_flipbook_from_images,
358
  inputs=[images, img_view_mode, img_skin],
359
- outputs=img_output
360
  )
361
 
362
  gr.Markdown("""
363
- ### Usage Instructions:
364
- 1. Select the tab for your content type (PDF or images)
365
- 2. Upload your file(s)
366
- 3. Adjust view mode and skin in Advanced Settings (optional)
367
- 4. Click the Create Flipbook button
368
- 5. Interact with your flipbook in the output area
369
 
370
- ### Notes:
371
- - The first pages contain interactive elements and links as examples
372
- - For best results, use PDFs with clear text and images
373
- - Supported image formats: JPG, PNG, GIF, etc.
 
374
  """)
375
 
376
 
 
111
  thumb_path = os.path.join(thumbs_folder, f"thumb_{i + 1}.png")
112
  create_thumbnail(img_path, thumb_path)
113
 
114
+ # Add interactive content as simple text overlays to avoid compatibility issues
115
  html_content = ""
 
116
 
117
  if i == 0: # First image example with HTML content
118
  html_content = """
119
  <div style="position: absolute; top: 50px; left: 50px; background-color: rgba(255,255,255,0.7); padding: 10px; border-radius: 5px;">
120
+ <div style="color: #333; font-size: 18px; font-weight: bold;">์ด๋ฏธ์ง€ ๊ฐค๋Ÿฌ๋ฆฌ</div>
121
+ <div style="color: #666; margin-top: 5px;">๊ฐค๋Ÿฌ๋ฆฌ์˜ ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์ž…๋‹ˆ๋‹ค.</div>
122
+ </div>
123
+ """
124
+ elif i == 1: # Second image
125
+ html_content = """
126
+ <div style="position: absolute; top: 50px; left: 50px; background-color: rgba(255,255,255,0.7); padding: 10px; border-radius: 5px;">
127
+ <div style="color: #333; font-size: 18px; font-weight: bold;">๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€</div>
128
+ <div style="color: #666; margin-top: 5px;">ํŽ˜์ด์ง€๋ฅผ ๋„˜๊ธฐ๊ฑฐ๋‚˜ ๋ชจ์„œ๋ฆฌ๋ฅผ ๋“œ๋ž˜๊ทธํ•˜์—ฌ ์ด๋ฏธ์ง€๋ฅผ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.</div>
129
  </div>
130
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
+ # Create a simpler page structure to avoid potential compatibility issues
133
+ page_info = {
134
+ "src": dest_path.replace("\\", "/"), # Ensure forward slashes for web paths
135
+ "thumb": thumb_path.replace("\\", "/"),
136
+ "title": f"์ด๋ฏธ์ง€ {i + 1}",
137
+ "htmlContent": html_content if html_content else None
138
+ }
139
+
140
+ pages_info.append(page_info)
141
+ print(f"Processed image {i+1}: {dest_path}")
142
+
143
  except Exception as e:
144
  print(f"Error processing image {img_path}: {e}")
145
 
146
  return pages_info
147
 
148
+ def create_flipbook_from_pdf(pdf_file, view_mode="2d", skin="light"):
149
  """Create a flipbook from uploaded PDF."""
150
  try:
151
  session_id = str(uuid.uuid4())
152
  pages_info = []
153
+ debug_info = ""
154
 
155
  if pdf_file is not None:
156
  # In Gradio, pdf_file is a file path string, not the actual content
157
  pdf_path = pdf_file.name # Get the file path
158
+ debug_info += f"PDF path: {pdf_path}\n"
159
 
160
  # Process PDF using the file path directly
161
  pages_info = process_pdf(pdf_path, session_id)
162
+ debug_info += f"Number of pages processed: {len(pages_info)}\n"
163
  else:
164
+ return """<div style="color: red; padding: 20px;">PDF ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.</div>""", "No file uploaded"
165
 
166
  if not pages_info:
167
+ return """<div style="color: red; padding: 20px;">PDF ํŒŒ์ผ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.</div>""", "No pages processed"
168
 
169
  # Create and return HTML for the flipbook
170
  flipbook_html = generate_flipbook_html(pages_info, session_id, view_mode, skin)
171
+ debug_info += f"HTML generated with view mode: {view_mode}, skin: {skin}\n"
172
+ return flipbook_html, debug_info
173
 
174
  except Exception as e:
175
+ error_msg = f"Error creating flipbook from PDF: {e}"
176
+ print(error_msg)
177
+ return f"""<div style="color: red; padding: 20px;">์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}</div>""", error_msg
178
 
179
+ def create_flipbook_from_images(images, view_mode="2d", skin="light"):
180
  """Create a flipbook from uploaded images."""
181
  try:
182
  session_id = str(uuid.uuid4())
183
  pages_info = []
184
+ debug_info = ""
185
 
186
  if images is not None and len(images) > 0:
187
  # Process images using file paths
188
  image_paths = [img.name for img in images]
189
+ debug_info += f"Image paths: {image_paths}\n"
190
+
191
  pages_info = process_images(image_paths, session_id)
192
+ debug_info += f"Number of images processed: {len(pages_info)}\n"
193
  else:
194
+ return """<div style="color: red; padding: 20px;">์ตœ์†Œ ํ•œ ๊ฐœ ์ด์ƒ์˜ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.</div>""", "No images uploaded"
195
 
196
  if not pages_info:
197
+ return """<div style="color: red; padding: 20px;">์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.</div>""", "No images processed"
198
 
199
  # Create and return HTML for the flipbook
200
  flipbook_html = generate_flipbook_html(pages_info, session_id, view_mode, skin)
201
+ debug_info += f"HTML generated with view mode: {view_mode}, skin: {skin}\n"
202
+ return flipbook_html, debug_info
203
 
204
  except Exception as e:
205
+ error_msg = f"Error creating flipbook from images: {e}"
206
+ print(error_msg)
207
+ return f"""<div style="color: red; padding: 20px;">์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}</div>""", error_msg
208
 
209
  def generate_flipbook_html(pages_info, session_id, view_mode, skin):
210
  """Generate HTML for the flipbook."""
 
223
 
224
  # HTML template with embedded CSS and JavaScript
225
  html = f"""
226
+ <div style="height:700px; width:100%; position:relative; overflow:hidden; border:1px solid #ccc;">
227
+ <div id="{flipbook_id}" style="width:100%; height:100%;"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
 
229
  <script>
230
+ // Function to load scripts sequentially
231
+ function loadScript(src, callback) {{
232
+ let script = document.createElement('script');
233
+ script.src = src;
234
+ script.onload = callback;
235
+ document.head.appendChild(script);
236
+ }}
237
+
238
+ // Function to add CSS
239
+ function loadCSS(href) {{
240
+ let link = document.createElement('link');
241
+ link.rel = 'stylesheet';
242
+ link.type = 'text/css';
243
+ link.href = href;
244
+ document.head.appendChild(link);
245
+ }}
246
+
247
+ // Load CSS first
248
+ loadCSS('flipbook.css');
249
+
250
+ // Load scripts in sequence
251
+ loadScript('flipbook.js', function() {{
252
+ loadScript('flipbook.webgl.js', function() {{
253
+ loadScript('flipbook.swipe.js', function() {{
254
+ loadScript('flipbook.scroll.js', function() {{
255
+ loadScript('flipbook.book3.js', function() {{
256
+ // All scripts loaded, now initialize flipbook
257
+ const options = {{
258
+ pages: {pages_json},
259
+ viewMode: '{view_mode}',
260
+ skin: '{skin}',
261
+ responsiveView: true,
262
+ singlePageMode: false,
263
+ singlePageModeIfMobile: true,
264
+ pageFlipDuration: 1,
265
+ sound: true,
266
+ backgroundMusic: false,
267
+ thumbnailsOnStart: true,
268
+ btnThumbs: {{ enabled: true }},
269
+ btnPrint: {{ enabled: true }},
270
+ btnDownloadPages: {{ enabled: true }},
271
+ btnDownloadPdf: {{ enabled: true }},
272
+ btnShare: {{ enabled: true }},
273
+ btnSound: {{ enabled: true }},
274
+ btnExpand: {{ enabled: true }},
275
+ rightToLeft: false,
276
+ autoplayOnStart: false,
277
+ autoplayInterval: 3000
278
+ }};
279
+
280
+ try {{
281
+ const container = document.getElementById('{flipbook_id}');
282
+ if (container) {{
283
+ console.log("Container found, initializing flipbook");
284
+ new FlipBook(container, options);
285
+ }} else {{
286
+ console.error("Container not found: #{flipbook_id}");
287
+ }}
288
+ }} catch (error) {{
289
+ console.error("Error initializing flipbook:", error);
290
+ }}
291
+ }});
292
+ }});
293
+ }});
294
+ }});
295
  }});
296
  </script>
297
+ </div>
298
+ <div style="margin-top:20px; padding:10px; background-color:#f5f5f5; border-radius:5px;">
299
+ <p><strong>์ฐธ๊ณ :</strong> ํ”Œ๋ฆฝ๋ถ์ด ๋ณด์ด์ง€ ์•Š๋Š” ๊ฒฝ์šฐ:</p>
300
+ <ol>
301
+ <li>ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจํ•˜์„ธ์š”.</li>
302
+ <li>๋‹ค๋ฅธ ๋ทฐ ๋ชจ๋“œ๋ฅผ ์„ ํƒํ•ด๋ณด์„ธ์š” (์›นGL ๋Œ€์‹  2D ๋˜๋Š” 3D).</li>
303
+ <li>๋ธŒ๋ผ์šฐ์ € ์ฝ˜์†”์—์„œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ํ™•์ธํ•˜์„ธ์š”.</li>
304
+ </ol>
305
+ </div>
306
  """
307
  return html
308
 
309
+ # Define the Gradio interface
310
  with gr.Blocks(title="3D Flipbook Viewer") as demo:
311
  gr.Markdown("# 3D Flipbook Viewer")
312
  gr.Markdown("""
313
+ ## 3D ํ”Œ๋ฆฝ๋ถ ๋ทฐ์–ด
314
 
315
+ PDF ํŒŒ์ผ์ด๋‚˜ ์—ฌ๋Ÿฌ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜์—ฌ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ 3D ํ”Œ๋ฆฝ๋ถ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
316
 
317
+ ### ํŠน์ง•:
318
+ - ํŽ˜์ด์ง€ ๋„˜๊น€ ํšจ๊ณผ์™€ ํ•จ๊ป˜ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒํ•œ ๊ธฐ๋Šฅ ์ œ๊ณต
319
+ - ์ฒซ ํŽ˜์ด์ง€์—๋Š” ์˜ˆ์‹œ๋กœ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ์š”์†Œ๊ฐ€ ํฌํ•จ๋จ
320
+ - ํˆด๋ฐ”๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ํŽ˜์ด์ง€ ๋ชจ์„œ๋ฆฌ๋ฅผ ๋“œ๋ž˜๊ทธํ•˜์—ฌ ํƒ์ƒ‰
321
+ - ์ธ๋„ค์ผ ๋ณด๊ธฐ๋กœ ๋น ๋ฅธ ํƒ์ƒ‰ ๊ฐ€๋Šฅ
322
+ - ์ „์ฒด ํ™”๋ฉด์œผ๋กœ ์ „ํ™˜ํ•˜์—ฌ ๋” ๋‚˜์€ ๋ณด๊ธฐ ๊ฒฝํ—˜
323
  """)
324
 
325
  with gr.Tabs():
326
+ with gr.TabItem("PDF ์—…๋กœ๋“œ"):
327
+ pdf_file = gr.File(label="PDF ํŒŒ์ผ ์—…๋กœ๋“œ", file_types=[".pdf"])
328
 
329
+ with gr.Accordion("๊ณ ๊ธ‰ ์„ค์ •", open=False):
330
+ pdf_view_mode = gr.Radio(
331
  choices=["webgl", "3d", "2d", "swipe"],
332
+ value="2d", # Changed default to 2d for better compatibility
333
+ label="๋ทฐ ๋ชจ๋“œ",
334
+ info="WebGL: ์ตœ๊ณ  ํ’ˆ์งˆ, 2D: ๊ฐ€์žฅ ์•ˆ์ •์ , 3D: ์ค‘๊ฐ„, Swipe: ๋ชจ๋ฐ”์ผ์šฉ"
335
  )
336
+ pdf_skin = gr.Radio(
337
  choices=["light", "dark", "gradient"],
338
  value="light",
339
+ label="์Šคํ‚จ",
340
+ info="light: ๋ฐ์€ ํ…Œ๋งˆ, dark: ์–ด๋‘์šด ํ…Œ๋งˆ, gradient: ๊ทธ๋ผ๋ฐ์ด์…˜ ํ…Œ๋งˆ"
341
  )
342
 
343
+ pdf_create_btn = gr.Button("PDF์—์„œ ํ”Œ๋ฆฝ๋ถ ๋งŒ๋“ค๊ธฐ", variant="primary", size="lg")
344
+ pdf_debug = gr.Textbox(label="๋””๋ฒ„๊ทธ ์ •๋ณด", visible=False)
345
+ pdf_output = gr.HTML(label="ํ”Œ๋ฆฝ๋ถ ๊ฒฐ๊ณผ๋ฌผ")
346
 
347
  # Set up PDF event handler
348
  pdf_create_btn.click(
349
  fn=create_flipbook_from_pdf,
350
  inputs=[pdf_file, pdf_view_mode, pdf_skin],
351
+ outputs=[pdf_output, pdf_debug]
352
  )
353
 
354
+ with gr.TabItem("์ด๋ฏธ์ง€ ์—…๋กœ๋“œ"):
355
+ images = gr.File(label="์ด๋ฏธ์ง€ ํŒŒ์ผ ์—…๋กœ๋“œ", file_types=["image"], file_count="multiple")
356
 
357
+ with gr.Accordion("๊ณ ๊ธ‰ ์„ค์ •", open=False):
358
+ img_view_mode = gr.Radio(
359
  choices=["webgl", "3d", "2d", "swipe"],
360
+ value="2d", # Changed default to 2d for better compatibility
361
+ label="๋ทฐ ๋ชจ๋“œ",
362
+ info="WebGL: ์ตœ๊ณ  ํ’ˆ์งˆ, 2D: ๊ฐ€์žฅ ์•ˆ์ •์ , 3D: ์ค‘๊ฐ„, Swipe: ๋ชจ๋ฐ”์ผ์šฉ"
363
  )
364
+ img_skin = gr.Radio(
365
  choices=["light", "dark", "gradient"],
366
  value="light",
367
+ label="์Šคํ‚จ",
368
+ info="light: ๋ฐ์€ ํ…Œ๋งˆ, dark: ์–ด๋‘์šด ํ…Œ๋งˆ, gradient: ๊ทธ๋ผ๋ฐ์ด์…˜ ํ…Œ๋งˆ"
369
  )
370
 
371
+ img_create_btn = gr.Button("์ด๋ฏธ์ง€์—์„œ ํ”Œ๋ฆฝ๋ถ ๋งŒ๋“ค๊ธฐ", variant="primary", size="lg")
372
+ img_debug = gr.Textbox(label="๋””๋ฒ„๊ทธ ์ •๋ณด", visible=False)
373
+ img_output = gr.HTML(label="ํ”Œ๋ฆฝ๋ถ ๊ฒฐ๊ณผ๋ฌผ")
374
 
375
  # Set up image event handler
376
  img_create_btn.click(
377
  fn=create_flipbook_from_images,
378
  inputs=[images, img_view_mode, img_skin],
379
+ outputs=[img_output, img_debug]
380
  )
381
 
382
  gr.Markdown("""
383
+ ### ์‚ฌ์šฉ๋ฒ•:
384
+ 1. ์ปจํ…์ธ  ์œ ํ˜•์— ๋”ฐ๋ผ ํƒญ์„ ์„ ํƒํ•˜์„ธ์š” (PDF ๋˜๋Š” ์ด๋ฏธ์ง€)
385
+ 2. ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•˜์„ธ์š”
386
+ 3. ํ•„์š”์— ๋”ฐ๋ผ ๊ณ ๊ธ‰ ์„ค์ •์—์„œ ๋ทฐ ๋ชจ๋“œ์™€ ์Šคํ‚จ์„ ์กฐ์ •ํ•˜์„ธ์š”
387
+ 4. ํ”Œ๋ฆฝ๋ถ ๋งŒ๋“ค๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์„ธ์š”
388
+ 5. ์ถœ๋ ฅ ์˜์—ญ์—์„œ ํ”Œ๋ฆฝ๋ถ๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜์„ธ์š”
389
 
390
+ ### ์ฐธ๊ณ :
391
+ - ์ฒ˜์Œ ํŽ˜์ด์ง€์—๋Š” ์˜ˆ์‹œ๋กœ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ์š”์†Œ์™€ ๋งํฌ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค
392
+ - ์ตœ์ƒ์˜ ๊ฒฐ๊ณผ๋ฅผ ์œ„ํ•ด ์„ ๋ช…ํ•œ ํ…์ŠคํŠธ์™€ ์ด๋ฏธ์ง€๊ฐ€ ์žˆ๋Š” PDF๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”
393
+ - ์ง€์›๋˜๋Š” ์ด๋ฏธ์ง€ ํ˜•์‹: JPG, PNG, GIF ๋“ฑ
394
+ - ํ”Œ๋ฆฝ๋ถ์ด ๋ณด์ด์ง€ ์•Š๋Š” ๊ฒฝ์šฐ, 2D ๋ชจ๋“œ๋ฅผ ์„ ํƒํ•˜๊ณ  ๋‹ค์‹œ ์‹œ๋„ํ•ด๋ณด์„ธ์š”
395
  """)
396
 
397