r0mant1c commited on
Commit
bcda10a
·
1 Parent(s): 840d1c1

Render uploaded document preview

Browse files
Files changed (1) hide show
  1. app.py +65 -19
app.py CHANGED
@@ -4,6 +4,9 @@ import os
4
  import re
5
  import time
6
  import traceback
 
 
 
7
  from html import escape
8
  from typing import Any
9
 
@@ -187,41 +190,68 @@ def upload_state(uploaded_file: str | None) -> tuple[Any, Any]:
187
  )
188
 
189
  filename = os.path.basename(uploaded_file)
 
190
  return (
191
  gr.update(visible=False),
192
- gr.update(visible=True, value=selected_document_html(filename)),
193
  workflow_phase_html("processing"),
194
  )
195
 
196
 
197
- def selected_document_html(filename: str | None = None) -> str:
198
  if not filename:
199
  filename = "Document ready"
200
- return f"""
201
- <section class="bte-selected-document">
202
- <div class="bte-selected-preview" aria-hidden="true">
203
- <div class="bte-selected-preview-frame">
 
204
  <div class="bte-selected-preview-header">
205
  <span></span><span></span><span></span>
206
  </div>
207
- <div class="bte-selected-preview-body">
208
- <div class="bte-preview-line bte-preview-line--title"></div>
209
- <div class="bte-preview-line bte-preview-line--lg"></div>
210
- <div class="bte-preview-line bte-preview-line--md"></div>
211
- <div class="bte-preview-line bte-preview-line--sm"></div>
212
- <div class="bte-preview-grid">
213
- <span></span><span></span><span></span>
214
- <span></span><span></span><span></span>
215
- </div>
216
- <div class="bte-preview-watermark">{escape(filename)}</div>
217
- </div>
218
  </div>
 
 
 
 
 
 
219
  <div class="bte-selected-preview-overlay"></div>
 
220
  </div>
221
  </section>
222
  """
223
 
224
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  def empty_report_html(
226
  title: str = "Report preview",
227
  detail: str = "Extracted lab markers will render here as an interactive medical document.",
@@ -1749,10 +1779,23 @@ gradio-app,
1749
  overflow: hidden;
1750
  }
1751
 
1752
- .bte-selected-preview-frame {
 
1753
  position: absolute;
1754
  inset: 18px;
1755
  border-radius: 20px;
 
 
 
 
 
 
 
 
 
 
 
 
1756
  background:
1757
  linear-gradient(180deg, rgba(255, 255, 255, 0.97), rgba(245, 248, 252, 0.96));
1758
  border: 1px solid rgba(217, 226, 238, 0.82);
@@ -1819,7 +1862,10 @@ gradio-app,
1819
  }
1820
 
1821
  .bte-preview-watermark {
1822
- margin-top: 18px;
 
 
 
1823
  color: rgba(17, 24, 39, 0.2);
1824
  font-size: 18px;
1825
  font-weight: 700;
 
4
  import re
5
  import time
6
  import traceback
7
+ import base64
8
+ import io
9
+ from pathlib import Path
10
  from html import escape
11
  from typing import Any
12
 
 
190
  )
191
 
192
  filename = os.path.basename(uploaded_file)
193
+ preview_data_url = _uploaded_file_preview_data_url(uploaded_file)
194
  return (
195
  gr.update(visible=False),
196
+ gr.update(visible=True, value=selected_document_html(filename, preview_data_url)),
197
  workflow_phase_html("processing"),
198
  )
199
 
200
 
201
+ def selected_document_html(filename: str | None = None, preview_data_url: str | None = None) -> str:
202
  if not filename:
203
  filename = "Document ready"
204
+ preview_markup = (
205
+ f'<img class="bte-upload-preview-image" src="{escape(preview_data_url)}" alt="Uploaded document preview">'
206
+ if preview_data_url
207
+ else """
208
+ <div class="bte-upload-preview-placeholder">
209
  <div class="bte-selected-preview-header">
210
  <span></span><span></span><span></span>
211
  </div>
 
 
 
 
 
 
 
 
 
 
 
212
  </div>
213
+ """
214
+ )
215
+ return f"""
216
+ <section class="bte-selected-document">
217
+ <div class="bte-selected-preview" aria-hidden="true">
218
+ {preview_markup}
219
  <div class="bte-selected-preview-overlay"></div>
220
+ <div class="bte-preview-watermark">{escape(filename)}</div>
221
  </div>
222
  </section>
223
  """
224
 
225
 
226
+ def _uploaded_file_preview_data_url(uploaded_file: str) -> str | None:
227
+ path = Path(uploaded_file)
228
+ suffix = path.suffix.lower()
229
+
230
+ if suffix in {".png", ".jpg", ".jpeg", ".webp", ".tif", ".tiff"}:
231
+ from PIL import Image, ImageOps
232
+
233
+ with Image.open(path) as image:
234
+ image = ImageOps.exif_transpose(image).convert("RGB")
235
+ image.thumbnail((1200, 1200))
236
+ buffer = io.BytesIO()
237
+ image.save(buffer, format="JPEG", quality=86, optimize=True)
238
+ encoded = base64.b64encode(buffer.getvalue()).decode("ascii")
239
+ return f"data:image/jpeg;base64,{encoded}"
240
+
241
+ if suffix == ".pdf":
242
+ import fitz
243
+
244
+ with fitz.open(path) as document:
245
+ if document.page_count == 0:
246
+ return None
247
+ page = document.load_page(0)
248
+ pixmap = page.get_pixmap(matrix=fitz.Matrix(2, 2), alpha=False)
249
+ encoded = base64.b64encode(pixmap.tobytes("png")).decode("ascii")
250
+ return f"data:image/png;base64,{encoded}"
251
+
252
+ return None
253
+
254
+
255
  def empty_report_html(
256
  title: str = "Report preview",
257
  detail: str = "Extracted lab markers will render here as an interactive medical document.",
 
1779
  overflow: hidden;
1780
  }
1781
 
1782
+ .bte-upload-preview-image,
1783
+ .bte-upload-preview-placeholder {
1784
  position: absolute;
1785
  inset: 18px;
1786
  border-radius: 20px;
1787
+ }
1788
+
1789
+ .bte-upload-preview-image {
1790
+ width: calc(100% - 36px);
1791
+ height: calc(100% - 36px);
1792
+ object-fit: cover;
1793
+ filter: blur(1.8px) saturate(0.78) contrast(0.92);
1794
+ transform: scale(1.03);
1795
+ box-shadow: 0 16px 35px rgba(18, 32, 56, 0.08);
1796
+ }
1797
+
1798
+ .bte-upload-preview-placeholder {
1799
  background:
1800
  linear-gradient(180deg, rgba(255, 255, 255, 0.97), rgba(245, 248, 252, 0.96));
1801
  border: 1px solid rgba(217, 226, 238, 0.82);
 
1862
  }
1863
 
1864
  .bte-preview-watermark {
1865
+ position: absolute;
1866
+ left: 34px;
1867
+ right: 34px;
1868
+ bottom: 28px;
1869
  color: rgba(17, 24, 39, 0.2);
1870
  font-size: 18px;
1871
  font-weight: 700;