Spaces:
Runtime error
Runtime error
| import fitz # PyMuPDF | |
| from PIL import Image | |
| import io | |
| import json | |
| def build_searchable_pdf(image_list, ocr_results_list, output_path="searchable.pdf"): | |
| doc = fitz.open() | |
| for i, (image, ocr_data) in enumerate(zip(image_list, ocr_results_list)): | |
| # Convert PIL Image to bytes for embedding | |
| img_byte_arr = io.BytesIO() | |
| image.save(img_byte_arr, format='PNG') # Use PNG for lossless quality | |
| img_bytes = img_byte_arr.getvalue() | |
| # Create a new page with the original image dimensions | |
| img_width, img_height = image.size | |
| page = doc.new_page(width=img_width, height=img_height) | |
| # Embed the original image as the background | |
| rect = fitz.Rect(0, 0, img_width, img_height) | |
| page.insert_image(rect, stream=img_bytes) | |
| # Directly use OCR results (now assumed to be a dictionary) | |
| if not isinstance(ocr_data, dict): | |
| print(f"Warning: OCR result for page {i} is not a dictionary. Skipping text layer.") | |
| continue | |
| # Place invisible text at exact coordinates | |
| for word_data in ocr_data.get('words', []): | |
| word_text = word_data.get('text') | |
| bbox = word_data.get('bbox') # [x0, y0, x1, y1] | |
| if word_text and bbox and len(bbox) == 4: | |
| # PyMuPDF uses (x0, y0, x1, y1) for rects | |
| text_rect = fitz.Rect(bbox[0], bbox[1], bbox[2], bbox[3]) | |
| # A simple approach to estimate font size based on bbox height | |
| font_size = max(1, bbox[3] - bbox[1]) | |
| # Insert text, making it invisible (render_mode=3) | |
| # You might need to adjust text_rect coordinates or font_size for better alignment | |
| page.insert_textbox(text_rect, word_text, | |
| fontsize=font_size, | |
| render_mode=3, # Invisible text | |
| fill=None) # No fill color needed for invisible text | |
| doc.save(output_path) | |
| doc.close() | |
| return output_path | |