ginipick commited on
Commit
c81c490
·
verified ·
1 Parent(s): 8b7579c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +242 -0
app.py ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ from PIL import Image
9
+ import fitz # PyMuPDF for PDF handling
10
+
11
+ # Constants
12
+ TEMP_DIR = "temp"
13
+ UPLOAD_DIR = os.path.join(TEMP_DIR, "uploads")
14
+ OUTPUT_DIR = os.path.join(TEMP_DIR, "output")
15
+ THUMBS_DIR = os.path.join(OUTPUT_DIR, "thumbs")
16
+
17
+ # Ensure directories exist
18
+ for dir_path in [TEMP_DIR, UPLOAD_DIR, OUTPUT_DIR, THUMBS_DIR]:
19
+ os.makedirs(dir_path, exist_ok=True)
20
+
21
+ def create_thumbnail(image_path, output_path, size=(300, 300)):
22
+ """Create a thumbnail from an image."""
23
+ try:
24
+ with Image.open(image_path) as img:
25
+ img.thumbnail(size, Image.LANCZOS)
26
+ img.save(output_path)
27
+ return output_path
28
+ except Exception as e:
29
+ print(f"Error creating thumbnail: {e}")
30
+ return None
31
+
32
+ def process_pdf(pdf_path, session_id):
33
+ """Extract pages from a PDF and save as images with thumbnails."""
34
+ pages_info = []
35
+ output_folder = os.path.join(OUTPUT_DIR, session_id)
36
+ thumbs_folder = os.path.join(THUMBS_DIR, session_id)
37
+
38
+ os.makedirs(output_folder, exist_ok=True)
39
+ os.makedirs(thumbs_folder, exist_ok=True)
40
+
41
+ try:
42
+ # Open the PDF
43
+ pdf_document = fitz.open(pdf_path)
44
+
45
+ # Process each page
46
+ for page_num, page in enumerate(pdf_document):
47
+ # Render page to an image with a higher resolution
48
+ pix = page.get_pixmap(matrix=fitz.Matrix(2, 2))
49
+ image_path = os.path.join(output_folder, f"page_{page_num + 1}.png")
50
+ pix.save(image_path)
51
+
52
+ # Create thumbnail
53
+ thumb_path = os.path.join(thumbs_folder, f"thumb_{page_num + 1}.png")
54
+ create_thumbnail(image_path, thumb_path)
55
+
56
+ # Add page info
57
+ pages_info.append({
58
+ "src": os.path.join("output", session_id, f"page_{page_num + 1}.png"),
59
+ "thumb": os.path.join("thumbs", session_id, f"thumb_{page_num + 1}.png"),
60
+ "title": f"Page {page_num + 1}"
61
+ })
62
+
63
+ return pages_info
64
+ except Exception as e:
65
+ print(f"Error processing PDF: {e}")
66
+ return []
67
+
68
+ def process_images(image_paths, session_id):
69
+ """Process uploaded images and create thumbnails."""
70
+ pages_info = []
71
+ output_folder = os.path.join(OUTPUT_DIR, session_id)
72
+ thumbs_folder = os.path.join(THUMBS_DIR, session_id)
73
+
74
+ os.makedirs(output_folder, exist_ok=True)
75
+ os.makedirs(thumbs_folder, exist_ok=True)
76
+
77
+ for i, img_path in enumerate(image_paths):
78
+ try:
79
+ # Copy original image to output folder
80
+ dest_path = os.path.join(output_folder, f"image_{i + 1}.png")
81
+ shutil.copy(img_path, dest_path)
82
+
83
+ # Create thumbnail
84
+ thumb_path = os.path.join(thumbs_folder, f"thumb_{i + 1}.png")
85
+ create_thumbnail(img_path, thumb_path)
86
+
87
+ # Add page info
88
+ pages_info.append({
89
+ "src": os.path.join("output", session_id, f"image_{i + 1}.png"),
90
+ "thumb": os.path.join("thumbs", session_id, f"thumb_{i + 1}.png"),
91
+ "title": f"Page {i + 1}"
92
+ })
93
+ except Exception as e:
94
+ print(f"Error processing image {img_path}: {e}")
95
+
96
+ return pages_info
97
+
98
+ def create_flipbook(upload_type, pdf_file=None, images=None, view_mode="webgl", skin="light"):
99
+ """Create a flipbook from uploaded PDF or images."""
100
+ try:
101
+ session_id = str(uuid.uuid4())
102
+ pages_info = []
103
+
104
+ # Process based on upload type
105
+ if upload_type == "pdf" and pdf_file is not None:
106
+ # Save PDF to temp directory
107
+ pdf_path = os.path.join(UPLOAD_DIR, f"{session_id}.pdf")
108
+ with open(pdf_path, "wb") as f:
109
+ f.write(pdf_file)
110
+
111
+ # Process PDF
112
+ pages_info = process_pdf(pdf_path, session_id)
113
+ elif upload_type == "images" and images is not None:
114
+ # Process images
115
+ pages_info = process_images(images, session_id)
116
+ else:
117
+ return """<div style="color: red; padding: 20px;">Please upload a PDF file or images.</div>"""
118
+
119
+ if not pages_info:
120
+ return """<div style="color: red; padding: 20px;">Failed to process the uploaded file(s). Please try again.</div>"""
121
+
122
+ # Create and return HTML for the flipbook
123
+ flipbook_html = generate_flipbook_html(pages_info, session_id, view_mode, skin)
124
+ return flipbook_html
125
+
126
+ except Exception as e:
127
+ print(f"Error creating flipbook: {e}")
128
+ return f"""<div style="color: red; padding: 20px;">An error occurred: {str(e)}</div>"""
129
+
130
+ def generate_flipbook_html(pages_info, session_id, view_mode, skin):
131
+ """Generate HTML for the flipbook."""
132
+ # Convert pages_info to JSON for JavaScript
133
+ pages_json = json.dumps(pages_info)
134
+
135
+ # Create a custom ID for this flipbook
136
+ flipbook_id = f"flipbook_{session_id}"
137
+
138
+ # HTML template with embedded CSS and JavaScript
139
+ html = f"""
140
+ <!DOCTYPE html>
141
+ <html>
142
+ <head>
143
+ <meta charset="UTF-8">
144
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
145
+ <title>3D Flipbook</title>
146
+ <style>
147
+ #flipbook-container {{
148
+ width: 100%;
149
+ height: 600px;
150
+ margin: 0 auto;
151
+ position: relative;
152
+ }}
153
+ body, html {{
154
+ margin: 0;
155
+ padding: 0;
156
+ height: 100%;
157
+ overflow: hidden;
158
+ }}
159
+ </style>
160
+ <link rel="stylesheet" type="text/css" href="flipbook.css">
161
+ </head>
162
+ <body>
163
+ <div id="{flipbook_id}" class="flipbook-container"></div>
164
+
165
+ <script src="flipbook.js"></script>
166
+ <script src="flipbook.webgl.js"></script>
167
+ <script src="flipbook.swipe.js"></script>
168
+ <script src="flipbook.scroll.js"></script>
169
+ <script src="flipbook.book3.js"></script>
170
+
171
+ <script>
172
+ // Initialize flipbook when page loads
173
+ document.addEventListener('DOMContentLoaded', function() {{
174
+ const options = {{
175
+ pages: {pages_json},
176
+ viewMode: '{view_mode}',
177
+ skin: '{skin}',
178
+ responsiveView: true,
179
+ singlePageMode: false,
180
+ singlePageModeIfMobile: true,
181
+ pageFlipDuration: 1,
182
+ sound: false,
183
+ thumbnailsOnStart: true,
184
+ btnThumbs: {{ enabled: true }},
185
+ btnPrint: {{ enabled: false }},
186
+ btnDownloadPages: {{ enabled: false }},
187
+ btnDownloadPdf: {{ enabled: false }}
188
+ }};
189
+
190
+ const container = document.getElementById('{flipbook_id}');
191
+ new FlipBook(container, options);
192
+ }});
193
+ </script>
194
+ </body>
195
+ </html>
196
+ """
197
+ return html
198
+
199
+ # Define the Gradio interface
200
+ with gr.Blocks(title="3D Flipbook Viewer") as demo:
201
+ gr.Markdown("# 3D Flipbook Viewer")
202
+ gr.Markdown("Upload a PDF file or multiple images to create an interactive 3D flipbook.")
203
+
204
+ with gr.Tabs():
205
+ with gr.TabItem("PDF Upload"):
206
+ pdf_file = gr.File(label="Upload PDF", file_types=[".pdf"])
207
+ pdf_create_btn = gr.Button("Create Flipbook from PDF")
208
+
209
+ with gr.TabItem("Image Upload"):
210
+ images = gr.File(label="Upload Images", file_types=["image"], file_count="multiple")
211
+ img_create_btn = gr.Button("Create Flipbook from Images")
212
+
213
+ with gr.Accordion("Advanced Settings", open=False):
214
+ view_mode = gr.Dropdown(
215
+ choices=["webgl", "3d", "2d", "swipe"],
216
+ value="webgl",
217
+ label="View Mode"
218
+ )
219
+ skin = gr.Dropdown(
220
+ choices=["light", "dark", "gradient"],
221
+ value="light",
222
+ label="Skin"
223
+ )
224
+
225
+ output = gr.HTML(label="Flipbook Output")
226
+
227
+ # Set up event handlers
228
+ pdf_create_btn.click(
229
+ fn=create_flipbook,
230
+ inputs=[gr.Textbox(value="pdf", visible=False), pdf_file, None, view_mode, skin],
231
+ outputs=output
232
+ )
233
+
234
+ img_create_btn.click(
235
+ fn=create_flipbook,
236
+ inputs=[gr.Textbox(value="images", visible=False), None, images, view_mode, skin],
237
+ outputs=output
238
+ )
239
+
240
+ # Launch the app
241
+ if __name__ == "__main__":
242
+ demo.launch()