# ocr_tab.py """Structured document OCR panel.""" from __future__ import annotations import base64 import io import json from typing import Any, Optional, Tuple import gradio as gr from PIL import Image from core.bootstrap import get_chart_extractor_service from gradio_ui.renderers import render_structured_ocr def _preview_image(preview_b64: Optional[str]): if not preview_b64: return None try: raw = base64.b64decode(preview_b64) return Image.open(io.BytesIO(raw)) except Exception: return None def run_structured_ocr( file_path: str | None, page_num: int ) -> Tuple[Optional[Any], str, gr.update, str, str]: if not file_path: return ( None, "
Upload a document to extract structured OCR.
", gr.update(), "", "0 fields / rows", ) with open(file_path, "rb") as handle: content = handle.read() filename = file_path.rsplit("\\", 1)[-1].rsplit("/", 1)[-1] extractor = get_chart_extractor_service() structured = extractor.extract_structured(content, filename) preview_b64 = extractor.preview_page(content, filename, page_num=page_num) pages = structured.get("pages") or [] page_choices = [p.get("page_number", idx + 1) for idx, p in enumerate(pages)] if not page_choices: page_choices = [1] if page_num not in page_choices: page_num = page_choices[0] html = render_structured_ocr(structured, page_num=page_num) image = _preview_image(preview_b64) field_count = 0 if pages: target = next((p for p in pages if p.get("page_number") == page_num), pages[0]) for section in target.get("sections") or []: field_count += len(section.get("fields") or {}) field_count += len(section.get("rows") or []) meta = f'' return image, html, gr.update(choices=page_choices, value=page_num), json.dumps(structured), meta def on_page_change(structured_json: str, page_num: int) -> str: if not structured_json: return "No structured data.
" return render_structured_ocr(json.loads(structured_json), page_num=page_num) def build_ocr_panel() -> dict: structured_state = gr.State("") with gr.Column(elem_classes=["fs-ocr-panel"]): ocr_file = gr.File( label="Upload PDF or image for OCR ยท PDF, PNG, JPG, TIFF", file_types=[".pdf", ".png", ".jpg", ".jpeg", ".tiff", ".bmp", ".webp"], type="filepath", elem_classes=["fs-upload-zone", "fs-ocr-upload"], file_count="single", height=140, ) with gr.Row(elem_classes=["fs-ocr-toolbar"]): page_selector = gr.Radio( label="Page", choices=[1], value=1, interactive=True, elem_classes=["fs-ocr-pages"], ) ocr_meta = gr.HTML('', padding=False) ocr_btn = gr.Button("Extract", elem_classes=["fs-gold-btn"], scale=0, min_width=100) with gr.Row(elem_classes=["fs-ocr-split"]): with gr.Column(elem_classes=["fs-ocr-pane", "fs-ocr-pane-left"]): gr.HTML('Labels and values taken from the document
""", padding=False, ) structured_html = gr.HTML( "Upload a file and click Extract.
", padding=False, ) ocr_btn.click( run_structured_ocr, inputs=[ocr_file, page_selector], outputs=[preview, structured_html, page_selector, structured_state, ocr_meta], queue=True, ) page_selector.change( on_page_change, inputs=[structured_state, page_selector], outputs=[structured_html], ) return { "ocr_file": ocr_file, "ocr_btn": ocr_btn, "preview": preview, "page_selector": page_selector, "structured_html": structured_html, }