Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,11 +1,9 @@
|
|
| 1 |
import os
|
| 2 |
import gradio as gr
|
| 3 |
import shutil
|
| 4 |
-
import tempfile
|
| 5 |
import uuid
|
| 6 |
from pathlib import Path
|
| 7 |
import json
|
| 8 |
-
import base64
|
| 9 |
from PIL import Image
|
| 10 |
import fitz # PyMuPDF for PDF handling
|
| 11 |
|
|
@@ -14,7 +12,7 @@ TEMP_DIR = "temp"
|
|
| 14 |
UPLOAD_DIR = os.path.join(TEMP_DIR, "uploads")
|
| 15 |
OUTPUT_DIR = os.path.join(TEMP_DIR, "output")
|
| 16 |
THUMBS_DIR = os.path.join(OUTPUT_DIR, "thumbs")
|
| 17 |
-
HTML_DIR = os.path.join(
|
| 18 |
|
| 19 |
# Ensure directories exist
|
| 20 |
for dir_path in [TEMP_DIR, UPLOAD_DIR, OUTPUT_DIR, THUMBS_DIR, HTML_DIR]:
|
|
@@ -66,18 +64,14 @@ def process_pdf(pdf_path, session_id):
|
|
| 66 |
</div>
|
| 67 |
"""
|
| 68 |
|
| 69 |
-
#
|
| 70 |
-
rel_image_path = os.path.relpath(image_path, HTML_DIR).replace("\\", "/")
|
| 71 |
-
rel_thumb_path = os.path.relpath(thumb_path, HTML_DIR).replace("\\", "/")
|
| 72 |
-
|
| 73 |
-
# Add page info with interactive content
|
| 74 |
pages_info.append({
|
| 75 |
-
"src":
|
| 76 |
-
"thumb":
|
| 77 |
"title": f"ํ์ด์ง {page_num + 1}",
|
| 78 |
"htmlContent": html_content if html_content else None
|
| 79 |
})
|
| 80 |
-
print(f"Processed PDF page {page_num+1}: {
|
| 81 |
|
| 82 |
return pages_info
|
| 83 |
except Exception as e:
|
|
@@ -121,20 +115,14 @@ def process_images(image_paths, session_id):
|
|
| 121 |
</div>
|
| 122 |
"""
|
| 123 |
|
| 124 |
-
#
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
# Create a simpler page structure to avoid potential compatibility issues
|
| 129 |
-
page_info = {
|
| 130 |
-
"src": rel_image_path,
|
| 131 |
-
"thumb": rel_thumb_path,
|
| 132 |
"title": f"์ด๋ฏธ์ง {i + 1}",
|
| 133 |
"htmlContent": html_content if html_content else None
|
| 134 |
-
}
|
| 135 |
-
|
| 136 |
-
pages_info.append(page_info)
|
| 137 |
-
print(f"Processed image {i+1}: {rel_image_path}")
|
| 138 |
|
| 139 |
except Exception as e:
|
| 140 |
print(f"Error processing image {img_path}: {e}")
|
|
@@ -153,20 +141,28 @@ def create_flipbook_from_pdf(pdf_file, view_mode="2d", skin="light"):
|
|
| 153 |
pdf_path = pdf_file.name # Get the file path
|
| 154 |
debug_info += f"PDF path: {pdf_path}\n"
|
| 155 |
|
| 156 |
-
#
|
| 157 |
-
|
| 158 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
else:
|
| 160 |
return """<div style="color: red; padding: 20px;">PDF ํ์ผ์ ์
๋ก๋ํด์ฃผ์ธ์.</div>""", "No file uploaded"
|
| 161 |
-
|
| 162 |
-
if not pages_info:
|
| 163 |
-
return """<div style="color: red; padding: 20px;">PDF ํ์ผ ์ฒ๋ฆฌ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ๋ค์ ์๋ํด์ฃผ์ธ์.</div>""", "No pages processed"
|
| 164 |
-
|
| 165 |
-
# Generate HTML file and return iframe HTML
|
| 166 |
-
iframe_html = generate_flipbook_html(pages_info, session_id, view_mode, skin)
|
| 167 |
-
debug_info += f"HTML file generated with view mode: {view_mode}, skin: {skin}\n"
|
| 168 |
-
|
| 169 |
-
return iframe_html, debug_info
|
| 170 |
|
| 171 |
except Exception as e:
|
| 172 |
error_msg = f"Error creating flipbook from PDF: {e}"
|
|
@@ -205,7 +201,7 @@ def create_flipbook_from_images(images, view_mode="2d", skin="light"):
|
|
| 205 |
return f"""<div style="color: red; padding: 20px;">์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค: {str(e)}</div>""", error_msg
|
| 206 |
|
| 207 |
def generate_flipbook_html(pages_info, session_id, view_mode, skin):
|
| 208 |
-
"""Generate a standalone HTML file for the flipbook and return
|
| 209 |
# Clean up pages_info to remove None values for JSON serialization
|
| 210 |
for page in pages_info:
|
| 211 |
if "htmlContent" in page and page["htmlContent"] is None:
|
|
@@ -228,7 +224,7 @@ def generate_flipbook_html(pages_info, session_id, view_mode, skin):
|
|
| 228 |
<meta charset="UTF-8">
|
| 229 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 230 |
<title>3D ํ๋ฆฝ๋ถ</title>
|
| 231 |
-
<link rel="stylesheet" type="text/css" href="
|
| 232 |
<style>
|
| 233 |
body, html {{
|
| 234 |
margin: 0;
|
|
@@ -265,11 +261,11 @@ def generate_flipbook_html(pages_info, session_id, view_mode, skin):
|
|
| 265 |
100% {{ transform: rotate(360deg); }}
|
| 266 |
}}
|
| 267 |
</style>
|
| 268 |
-
<script src="
|
| 269 |
-
<script src="
|
| 270 |
-
<script src="
|
| 271 |
-
<script src="
|
| 272 |
-
<script src="
|
| 273 |
</head>
|
| 274 |
<body>
|
| 275 |
<div id="flipbook-container"></div>
|
|
@@ -333,13 +329,16 @@ def generate_flipbook_html(pages_info, session_id, view_mode, skin):
|
|
| 333 |
with open(html_path, 'w', encoding='utf-8') as f:
|
| 334 |
f.write(html_content)
|
| 335 |
|
| 336 |
-
# Return
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
<div style="
|
| 340 |
-
<
|
|
|
|
|
|
|
| 341 |
</div>
|
| 342 |
-
|
|
|
|
| 343 |
<h3 style="margin-top:0; color:#333;">์ฌ์ฉ ํ:</h3>
|
| 344 |
<ul style="margin:10px 0; padding-left:20px;">
|
| 345 |
<li>ํ์ด์ง ๋ชจ์๋ฆฌ๋ฅผ ๋๋๊ทธํ์ฌ ๋๊ธธ ์ ์์ต๋๋ค.</li>
|
|
@@ -347,12 +346,25 @@ def generate_flipbook_html(pages_info, session_id, view_mode, skin):
|
|
| 347 |
<li>์ ์ฒดํ๋ฉด ๋ฒํผ์ ํด๋ฆญํ์ฌ ๋ ํฐ ํ๋ฉด์ผ๋ก ๋ณผ ์ ์์ต๋๋ค.</li>
|
| 348 |
</ul>
|
| 349 |
<div style="margin-top:10px; padding:10px; background-color:#e8f4fd; border-left:4px solid #2196F3; border-radius:2px;">
|
| 350 |
-
<strong>์ฐธ๊ณ :</strong>
|
| 351 |
</div>
|
| 352 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 353 |
"""
|
| 354 |
|
| 355 |
-
return
|
| 356 |
|
| 357 |
# Define the Gradio interface
|
| 358 |
with gr.Blocks(title="3D Flipbook Viewer") as demo:
|
|
@@ -445,4 +457,4 @@ with gr.Blocks(title="3D Flipbook Viewer") as demo:
|
|
| 445 |
|
| 446 |
# Launch the app
|
| 447 |
if __name__ == "__main__":
|
| 448 |
-
demo.launch(
|
|
|
|
| 1 |
import os
|
| 2 |
import gradio as gr
|
| 3 |
import shutil
|
|
|
|
| 4 |
import uuid
|
| 5 |
from pathlib import Path
|
| 6 |
import json
|
|
|
|
| 7 |
from PIL import Image
|
| 8 |
import fitz # PyMuPDF for PDF handling
|
| 9 |
|
|
|
|
| 12 |
UPLOAD_DIR = os.path.join(TEMP_DIR, "uploads")
|
| 13 |
OUTPUT_DIR = os.path.join(TEMP_DIR, "output")
|
| 14 |
THUMBS_DIR = os.path.join(OUTPUT_DIR, "thumbs")
|
| 15 |
+
HTML_DIR = os.path.join("public", "flipbooks") # Directory accessible via web
|
| 16 |
|
| 17 |
# Ensure directories exist
|
| 18 |
for dir_path in [TEMP_DIR, UPLOAD_DIR, OUTPUT_DIR, THUMBS_DIR, HTML_DIR]:
|
|
|
|
| 64 |
</div>
|
| 65 |
"""
|
| 66 |
|
| 67 |
+
# Add page info with web-accessible paths
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
pages_info.append({
|
| 69 |
+
"src": f"./temp/output/{session_id}/page_{page_num + 1}.png",
|
| 70 |
+
"thumb": f"./temp/output/thumbs/{session_id}/thumb_{page_num + 1}.png",
|
| 71 |
"title": f"ํ์ด์ง {page_num + 1}",
|
| 72 |
"htmlContent": html_content if html_content else None
|
| 73 |
})
|
| 74 |
+
print(f"Processed PDF page {page_num+1}: {image_path}")
|
| 75 |
|
| 76 |
return pages_info
|
| 77 |
except Exception as e:
|
|
|
|
| 115 |
</div>
|
| 116 |
"""
|
| 117 |
|
| 118 |
+
# Add page info with web-accessible paths
|
| 119 |
+
pages_info.append({
|
| 120 |
+
"src": f"./temp/output/{session_id}/image_{i + 1}.png",
|
| 121 |
+
"thumb": f"./temp/output/thumbs/{session_id}/thumb_{i + 1}.png",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
"title": f"์ด๋ฏธ์ง {i + 1}",
|
| 123 |
"htmlContent": html_content if html_content else None
|
| 124 |
+
})
|
| 125 |
+
print(f"Processed image {i+1}: {dest_path}")
|
|
|
|
|
|
|
| 126 |
|
| 127 |
except Exception as e:
|
| 128 |
print(f"Error processing image {img_path}: {e}")
|
|
|
|
| 141 |
pdf_path = pdf_file.name # Get the file path
|
| 142 |
debug_info += f"PDF path: {pdf_path}\n"
|
| 143 |
|
| 144 |
+
# Copy the PDF file to a location accessible by the public URL
|
| 145 |
+
pdf_public_path = os.path.join(HTML_DIR, f"pdf_{session_id}.pdf")
|
| 146 |
+
shutil.copy(pdf_path, pdf_public_path)
|
| 147 |
+
|
| 148 |
+
# Create a simple HTML page with direct PDF loading
|
| 149 |
+
html_filename = f"flipbook_{session_id}.html"
|
| 150 |
+
html_path = os.path.join(HTML_DIR, html_filename)
|
| 151 |
+
|
| 152 |
+
# Create HTML content that uses CDN resources
|
| 153 |
+
html_content = create_flipbook_html_page(f"pdf_{session_id}.pdf", session_id, view_mode, skin)
|
| 154 |
+
|
| 155 |
+
# Write the HTML file
|
| 156 |
+
with open(html_path, 'w', encoding='utf-8') as f:
|
| 157 |
+
f.write(html_content)
|
| 158 |
+
|
| 159 |
+
# Generate link to the HTML file
|
| 160 |
+
public_url = f"/public/flipbooks/{html_filename}"
|
| 161 |
+
flipbook_link = generate_flipbook_link(public_url, session_id, view_mode, skin)
|
| 162 |
+
|
| 163 |
+
return flipbook_link, debug_info
|
| 164 |
else:
|
| 165 |
return """<div style="color: red; padding: 20px;">PDF ํ์ผ์ ์
๋ก๋ํด์ฃผ์ธ์.</div>""", "No file uploaded"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
except Exception as e:
|
| 168 |
error_msg = f"Error creating flipbook from PDF: {e}"
|
|
|
|
| 201 |
return f"""<div style="color: red; padding: 20px;">์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค: {str(e)}</div>""", error_msg
|
| 202 |
|
| 203 |
def generate_flipbook_html(pages_info, session_id, view_mode, skin):
|
| 204 |
+
"""Generate a standalone HTML file for the flipbook and return link HTML."""
|
| 205 |
# Clean up pages_info to remove None values for JSON serialization
|
| 206 |
for page in pages_info:
|
| 207 |
if "htmlContent" in page and page["htmlContent"] is None:
|
|
|
|
| 224 |
<meta charset="UTF-8">
|
| 225 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 226 |
<title>3D ํ๋ฆฝ๋ถ</title>
|
| 227 |
+
<link rel="stylesheet" type="text/css" href="../flipbook.css">
|
| 228 |
<style>
|
| 229 |
body, html {{
|
| 230 |
margin: 0;
|
|
|
|
| 261 |
100% {{ transform: rotate(360deg); }}
|
| 262 |
}}
|
| 263 |
</style>
|
| 264 |
+
<script src="../flipbook.js"></script>
|
| 265 |
+
<script src="../flipbook.webgl.js"></script>
|
| 266 |
+
<script src="../flipbook.swipe.js"></script>
|
| 267 |
+
<script src="../flipbook.scroll.js"></script>
|
| 268 |
+
<script src="../flipbook.book3.js"></script>
|
| 269 |
</head>
|
| 270 |
<body>
|
| 271 |
<div id="flipbook-container"></div>
|
|
|
|
| 329 |
with open(html_path, 'w', encoding='utf-8') as f:
|
| 330 |
f.write(html_content)
|
| 331 |
|
| 332 |
+
# Return HTML with a direct link to open the flipbook in a new tab
|
| 333 |
+
public_url = f"/public/flipbooks/{html_filename}"
|
| 334 |
+
link_html = f"""
|
| 335 |
+
<div style="text-align:center; padding:20px; background-color:#f9f9f9; border-radius:5px; margin-bottom:20px;">
|
| 336 |
+
<h2 style="margin-top:0; color:#333;">ํ๋ฆฝ๋ถ์ด ์ค๋น๋์์ต๋๋ค!</h2>
|
| 337 |
+
<p style="margin-bottom:20px;">์๋ ๋ฒํผ์ ํด๋ฆญํ์ฌ ํ๋ฆฝ๋ถ์ ์ ์ฐฝ์์ ์ด์ด๋ณด์ธ์.</p>
|
| 338 |
+
<a href="{public_url}" target="_blank" style="display:inline-block; background-color:#4CAF50; color:white; padding:12px 24px; text-decoration:none; border-radius:4px; font-weight:bold; font-size:16px;">ํ๋ฆฝ๋ถ ์ด๊ธฐ</a>
|
| 339 |
</div>
|
| 340 |
+
|
| 341 |
+
<div style="margin-top:20px; padding:15px; background-color:#f5f5f5; border-radius:5px; line-height:1.5;">
|
| 342 |
<h3 style="margin-top:0; color:#333;">์ฌ์ฉ ํ:</h3>
|
| 343 |
<ul style="margin:10px 0; padding-left:20px;">
|
| 344 |
<li>ํ์ด์ง ๋ชจ์๋ฆฌ๋ฅผ ๋๋๊ทธํ์ฌ ๋๊ธธ ์ ์์ต๋๋ค.</li>
|
|
|
|
| 346 |
<li>์ ์ฒดํ๋ฉด ๋ฒํผ์ ํด๋ฆญํ์ฌ ๋ ํฐ ํ๋ฉด์ผ๋ก ๋ณผ ์ ์์ต๋๋ค.</li>
|
| 347 |
</ul>
|
| 348 |
<div style="margin-top:10px; padding:10px; background-color:#e8f4fd; border-left:4px solid #2196F3; border-radius:2px;">
|
| 349 |
+
<strong>์ฐธ๊ณ :</strong> ํ๋ฆฝ๋ถ์ 2D ๋ชจ๋์์ ๊ฐ์ฅ ์์ ์ ์ผ๋ก ์๋ํฉ๋๋ค.
|
| 350 |
</div>
|
| 351 |
</div>
|
| 352 |
+
|
| 353 |
+
<div style="margin-top:15px; background-color:#f5f5f5; border-radius:5px; padding:10px;">
|
| 354 |
+
<details>
|
| 355 |
+
<summary style="cursor:pointer; color:#2196F3; font-weight:bold;">๊ธฐ์ ์ ์ธ๋ถ์ฌํญ (๊ฐ๋ฐ์์ฉ)</summary>
|
| 356 |
+
<div style="margin-top:10px;">
|
| 357 |
+
<p>์ธ์
ID: {session_id}</p>
|
| 358 |
+
<p>HTML ํ์ผ ๊ฒฝ๋ก: {html_path}</p>
|
| 359 |
+
<p>ํ์ด์ง ์: {len(pages_info)}</p>
|
| 360 |
+
<p>๋ทฐ ๋ชจ๋: {view_mode}</p>
|
| 361 |
+
<p>์คํจ: {skin}</p>
|
| 362 |
+
</div>
|
| 363 |
+
</details>
|
| 364 |
+
</div>
|
| 365 |
"""
|
| 366 |
|
| 367 |
+
return link_html
|
| 368 |
|
| 369 |
# Define the Gradio interface
|
| 370 |
with gr.Blocks(title="3D Flipbook Viewer") as demo:
|
|
|
|
| 457 |
|
| 458 |
# Launch the app
|
| 459 |
if __name__ == "__main__":
|
| 460 |
+
demo.launch() # Remove share=True as it's not supported in Spaces
|