ChristianQ commited on
Commit
eb46107
·
1 Parent(s): a696b72

Fix Attempt #4 for coding module

Browse files
Files changed (1) hide show
  1. app.py +81 -109
app.py CHANGED
@@ -3,23 +3,23 @@ import uuid
3
  import shutil
4
  import traceback
5
  import json
 
6
  import gradio as gr
7
  from fastapi import FastAPI, File, UploadFile
8
- from fastapi.responses import JSONResponse
9
- from fastapi.middleware.cors import CORSMiddleware
10
  from fastapi.responses import JSONResponse, FileResponse
 
11
 
12
  from visualization import process_wireframe
13
  from CodingModule import HTMLGenerator
14
 
15
  # -----------------------------------------------------------------------------
16
- # FASTAPI (for Firebase / programmatic access)
17
  # -----------------------------------------------------------------------------
18
  api = FastAPI()
19
 
20
  api.add_middleware(
21
  CORSMiddleware,
22
- allow_origins=["*"], #Replace with the Firebase domain
23
  allow_credentials=True,
24
  allow_methods=["*"],
25
  allow_headers=["*"],
@@ -31,12 +31,18 @@ OUTPUT_DIR = "./output"
31
  os.makedirs(TEMP_DIR, exist_ok=True)
32
  os.makedirs(OUTPUT_DIR, exist_ok=True)
33
 
 
34
  @api.get("/")
35
  def health_check():
36
  return {"status": "ok"}
37
 
 
38
  @api.post("/process-wireframe")
39
  async def process_wireframe_api(image: UploadFile = File(...)):
 
 
 
 
40
  file_id = str(uuid.uuid4())
41
  temp_path = os.path.join(TEMP_DIR, f"{file_id}_{image.filename}")
42
 
@@ -56,82 +62,77 @@ async def process_wireframe_api(image: UploadFile = File(...)):
56
  status_code=400,
57
  content={"error": "No elements detected"}
58
  )
59
-
60
  json_path = results.get("json_path")
61
-
62
- # Read the JSON file content and return it directly
63
  json_content = None
64
  if json_path and os.path.exists(json_path):
65
  with open(json_path, "r") as f:
66
  json_content = json.load(f)
67
-
68
- # Generate styled HTML using CodingModule
69
  html_path = None
70
  try:
71
  html_generator = HTMLGenerator(json_path)
72
  html_filename = f"{file_id}_styled.html"
73
  html_path = os.path.join(OUTPUT_DIR, html_filename)
74
  html_generator.generate_html(html_path)
75
- except Exception as e:
76
- print(f"Warning: Could not generate styled HTML: {e}")
77
  html_path = results.get("html_path")
78
-
79
- # Read the HTML file content
80
  html_content = None
81
  if html_path and os.path.exists(html_path):
82
  with open(html_path, "r", encoding="utf-8") as f:
83
  html_content = f.read()
84
-
85
  return {
86
  "success": True,
87
- "json_data": json_content, # Return actual JSON content instead of path
88
- "html_content": html_content, # Return actual HTML content instead of path
89
  "total_elements": len(results["normalized_elements"]),
90
- "normalized_elements": results.get("normalized_elements", []) # Include normalized elements
91
  }
92
 
93
  except Exception as e:
94
  traceback.print_exc()
95
- return JSONResponse(
96
- status_code=500,
97
- content={"error": str(e)}
98
- )
99
 
100
  finally:
101
  if os.path.exists(temp_path):
102
  os.remove(temp_path)
103
 
104
- #Endpoint to serve generated HTML files
105
- @api.get("/view-html/{file_id}")
106
  async def serve_output_file(filename: str):
 
 
 
107
  file_path = os.path.join(OUTPUT_DIR, filename)
108
- if os.path.exists(file_path):
109
- if filename.endswith('.html'):
110
- return FileResponse(file_path, media_type="text/html")
111
- elif filename.endswith('.json'):
112
- return FileResponse(file_path, media_type="application/json")
113
- else:
114
- return FileResponse(file_path)
115
- return JSONResponse(status_code=404, content={"error": "File not Found"})
 
116
 
117
  # -----------------------------------------------------------------------------
118
- # GRADIO (for Hugging Face UI)
119
  # -----------------------------------------------------------------------------
120
  def gradio_process(image):
121
- """
122
- Gradio passes a PIL Image.
123
- We save it temporarily and reuse the SAME pipeline.
124
- """
125
  if image is None:
126
  return "Please upload an image", None, None
127
-
128
  file_id = str(uuid.uuid4())
129
  temp_path = os.path.join(TEMP_DIR, f"{file_id}.png")
130
-
131
- try:
132
  image.save(temp_path)
133
  except Exception as e:
134
- return f"Error saving image: {str(e)}", None, None
135
 
136
  try:
137
  results = process_wireframe(
@@ -141,28 +142,27 @@ def gradio_process(image):
141
  show_visualization=False
142
  )
143
 
144
- if not results or not results.get('normalized_elements'):
145
  return "No elements detected", None, None
146
 
147
- json_path = results.get("json_path")
148
-
149
- #Generate styled HTML using CodingModule
150
  try:
151
  html_generator = HTMLGenerator(json_path)
152
  html_filename = f"{file_id}_styled.html"
153
  html_path = os.path.join(OUTPUT_DIR, html_filename)
154
  html_generator.generate_html(html_path)
155
- except Exception as e:
156
- print(f"Warning: Could not generate styled HTML: {e}")
157
  traceback.print_exc()
158
  html_path = results.get("html_path")
159
-
160
- num_elements = len(results['normalized_elements'])
161
- status_msg = f"Successfully detected {num_elements} elemnts\n"
162
- status_msg += f"JSON: {os.path.basename(json_path)}\n"
163
- status_msg += f"HTML: {os.path.basename(html_path)}"
164
-
165
- return status_msg, json_path, html_path
166
 
167
  except Exception as e:
168
  traceback.print_exc()
@@ -172,71 +172,43 @@ def gradio_process(image):
172
  if os.path.exists(temp_path):
173
  os.remove(temp_path)
174
 
175
- # Enhanced Gradio interface with better UI
176
- with gr.Blocks(theme=gr.themes.Soft(), title="Wireframe Layout Normalizer") as demo:
 
 
 
 
177
  gr.Markdown("# Wireframe Layout Normalizer")
178
- gr.Markdown("Upload a wireframe image to extract and normalize UI layout elements")
179
-
180
- gr.Markdown("""
181
- ### Academic Research Project made by SeroTech 2025-2026 Holy Angel University
182
- This tool is part of a thesis project. Upload your wireframe sketch to automatically:
183
- - Detect UI elements (buttons, text fields, images, etc.)
184
- - Normalize positions and alignments
185
- - Export structured JSON data
186
- - Generate beautiful HTML preview
187
- """)
188
-
189
  with gr.Row():
190
- with gr.Column(scale=1):
191
  image_input = gr.Image(type="pil", label="Upload Wireframe Image")
192
- process_btn = gr.Button("Process Wireframe", variant="primary", size="lg")
193
-
194
- gr.Markdown("""
195
- #### Tips:
196
- - Upload clear wireframe sketches
197
- - PNG, JPG, or JPEG formats supported
198
- - Higher resolution = better detection
199
- """)
200
-
201
- with gr.Column(scale=1):
202
- status_output = gr.Textbox(
203
- label="Processing Status",
204
- lines=3,
205
- placeholder="Upload an image and click Process to begin..."
206
- )
207
- json_output = gr.File(label="Normalized JSON Output")
208
- html_output = gr.File(label="Generated HTML Preview")
209
-
210
  process_btn.click(
211
  fn=gradio_process,
212
  inputs=image_input,
213
- outputs=[status_output, json_output, html_output]
214
  )
215
-
216
- gr.Markdown("""
217
- ---
218
- ### How to use:
219
- 1. Upload a wireframe image (hand-drawn or digital)
220
- 2. Click "Process Wireframe" and wait for processing
221
- 3. Download the JSON file for structured data
222
- 4. Download the HTML file to see a styled preview
223
-
224
- ### Output Files:
225
- - JSON: Contains all detected elements with positions, types, and grid data
226
- - HTML: Beautiful, responsive preview with modern styling
227
-
228
- ### Technical Details:
229
- - Model: TensorFlow-based object detection
230
- - Grid System: 24-column responsive layout
231
- - Supported Elements: Buttons, Checkboxes, Text Fields, Images, Paragraphs, Text, Navbars
232
- """)
233
 
234
  # -----------------------------------------------------------------------------
235
- # ENTRY POINT (THIS IS IMPORTANT)
236
  # -----------------------------------------------------------------------------
237
- app = gr.mount_gradio_app(api, demo, path="/")
 
 
 
 
 
 
238
 
239
- if __name__ == "_main_":
240
  import uvicorn
241
- # For local testing
242
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
3
  import shutil
4
  import traceback
5
  import json
6
+
7
  import gradio as gr
8
  from fastapi import FastAPI, File, UploadFile
 
 
9
  from fastapi.responses import JSONResponse, FileResponse
10
+ from fastapi.middleware.cors import CORSMiddleware
11
 
12
  from visualization import process_wireframe
13
  from CodingModule import HTMLGenerator
14
 
15
  # -----------------------------------------------------------------------------
16
+ # FASTAPI BACKEND
17
  # -----------------------------------------------------------------------------
18
  api = FastAPI()
19
 
20
  api.add_middleware(
21
  CORSMiddleware,
22
+ allow_origins=["*"],
23
  allow_credentials=True,
24
  allow_methods=["*"],
25
  allow_headers=["*"],
 
31
  os.makedirs(TEMP_DIR, exist_ok=True)
32
  os.makedirs(OUTPUT_DIR, exist_ok=True)
33
 
34
+
35
  @api.get("/")
36
  def health_check():
37
  return {"status": "ok"}
38
 
39
+
40
  @api.post("/process-wireframe")
41
  async def process_wireframe_api(image: UploadFile = File(...)):
42
+ """
43
+ Firebase / Programmatic endpoint
44
+ Returns JSON + HTML content directly.
45
+ """
46
  file_id = str(uuid.uuid4())
47
  temp_path = os.path.join(TEMP_DIR, f"{file_id}_{image.filename}")
48
 
 
62
  status_code=400,
63
  content={"error": "No elements detected"}
64
  )
65
+
66
  json_path = results.get("json_path")
67
+
68
+ # Load JSON content
69
  json_content = None
70
  if json_path and os.path.exists(json_path):
71
  with open(json_path, "r") as f:
72
  json_content = json.load(f)
73
+
74
+ # Generate styled HTML
75
  html_path = None
76
  try:
77
  html_generator = HTMLGenerator(json_path)
78
  html_filename = f"{file_id}_styled.html"
79
  html_path = os.path.join(OUTPUT_DIR, html_filename)
80
  html_generator.generate_html(html_path)
81
+ except:
 
82
  html_path = results.get("html_path")
83
+
 
84
  html_content = None
85
  if html_path and os.path.exists(html_path):
86
  with open(html_path, "r", encoding="utf-8") as f:
87
  html_content = f.read()
88
+
89
  return {
90
  "success": True,
91
+ "json_data": json_content,
92
+ "html_content": html_content,
93
  "total_elements": len(results["normalized_elements"]),
94
+ "normalized_elements": results.get("normalized_elements", [])
95
  }
96
 
97
  except Exception as e:
98
  traceback.print_exc()
99
+ return JSONResponse(status_code=500, content={"error": str(e)})
 
 
 
100
 
101
  finally:
102
  if os.path.exists(temp_path):
103
  os.remove(temp_path)
104
 
105
+
106
+ @api.get("/view-html/{filename}")
107
  async def serve_output_file(filename: str):
108
+ """
109
+ Serve stored HTML/JSON files.
110
+ """
111
  file_path = os.path.join(OUTPUT_DIR, filename)
112
+ if not os.path.exists(file_path):
113
+ return JSONResponse(status_code=404, content={"error": "File not found"})
114
+
115
+ if filename.endswith(".html"):
116
+ return FileResponse(file_path, media_type="text/html")
117
+ elif filename.endswith(".json"):
118
+ return FileResponse(file_path, media_type="application/json")
119
+ return FileResponse(file_path)
120
+
121
 
122
  # -----------------------------------------------------------------------------
123
+ # GRADIO UI LOGIC
124
  # -----------------------------------------------------------------------------
125
  def gradio_process(image):
 
 
 
 
126
  if image is None:
127
  return "Please upload an image", None, None
128
+
129
  file_id = str(uuid.uuid4())
130
  temp_path = os.path.join(TEMP_DIR, f"{file_id}.png")
131
+
132
+ try:
133
  image.save(temp_path)
134
  except Exception as e:
135
+ return f"Error saving: {str(e)}", None, None
136
 
137
  try:
138
  results = process_wireframe(
 
142
  show_visualization=False
143
  )
144
 
145
+ if not results.get("normalized_elements"):
146
  return "No elements detected", None, None
147
 
148
+ json_path = results["json_path"]
149
+
150
+ # Generate styled HTML
151
  try:
152
  html_generator = HTMLGenerator(json_path)
153
  html_filename = f"{file_id}_styled.html"
154
  html_path = os.path.join(OUTPUT_DIR, html_filename)
155
  html_generator.generate_html(html_path)
156
+ except:
 
157
  traceback.print_exc()
158
  html_path = results.get("html_path")
159
+
160
+ num = len(results["normalized_elements"])
161
+ status = f"Detected {num} elements\n"
162
+ status += f"JSON: {os.path.basename(json_path)}\n"
163
+ status += f"HTML: {os.path.basename(html_path)}"
164
+
165
+ return status, json_path, html_path
166
 
167
  except Exception as e:
168
  traceback.print_exc()
 
172
  if os.path.exists(temp_path):
173
  os.remove(temp_path)
174
 
175
+
176
+ # -----------------------------------------------------------------------------
177
+ # GRADIO UI (updated for Gradio 6 compliance)
178
+ # -----------------------------------------------------------------------------
179
+ with gr.Blocks(title="Wireframe Layout Normalizer") as demo:
180
+
181
  gr.Markdown("# Wireframe Layout Normalizer")
182
+ gr.Markdown("Upload a wireframe image to extract and normalize UI layout elements.")
183
+
 
 
 
 
 
 
 
 
 
184
  with gr.Row():
185
+ with gr.Column():
186
  image_input = gr.Image(type="pil", label="Upload Wireframe Image")
187
+ process_btn = gr.Button("Process Wireframe")
188
+
189
+ with gr.Column():
190
+ status_output = gr.Textbox(label="Status")
191
+ json_output = gr.File(label="JSON Output")
192
+ html_output = gr.File(label="HTML Preview")
193
+
 
 
 
 
 
 
 
 
 
 
 
194
  process_btn.click(
195
  fn=gradio_process,
196
  inputs=image_input,
197
+ outputs=[status_output, json_output, html_output],
198
  )
199
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
 
201
  # -----------------------------------------------------------------------------
202
+ # FINAL APP MOUNT (fixes reload + /new spam)
203
  # -----------------------------------------------------------------------------
204
+ app = gr.mount_gradio_app(
205
+ api,
206
+ demo,
207
+ path="/gradio",
208
+ theme=gr.themes.Soft()
209
+ )
210
+
211
 
212
+ if __name__ == "__main__":
213
  import uvicorn
214
+ uvicorn.run(app, host="0.0.0.0", port=7860)