import gradio as gr import os import tempfile import numpy as np import cv2 import img2pdf import shutil import uuid from pathlib import Path from pdf2image import convert_from_path # pip install pdf2image opencv-python numpy img2pdf # Bounding box: (x1, y1, x2, y2) in fractions of image size default_bbox = (0.75, 0.9, 0.98, 0.98) def expand_bbox(bbox, expand_factor=0.3): x_min, y_min, x_max, y_max = bbox width = x_max - x_min height = y_max - y_min new_x_min = max(0, x_min - width * expand_factor) new_y_min = max(0, y_min - height * expand_factor) new_x_max = min(1, x_max + width * expand_factor) new_y_max = min(1, y_max + height * expand_factor) return (new_x_min, new_y_min, new_x_max, new_y_max) def inpaint_image(image_np, bbox, color=(255, 255, 255)): h, w, _ = image_np.shape x1 = int(bbox[0] * w) y1 = int(bbox[1] * h) x2 = int(bbox[2] * w) y2 = int(bbox[3] * h) inpainted_image = image_np.copy() cv2.rectangle(inpainted_image, (x1, y1), (x2, y2), color, -1) return inpainted_image def process_pdf(pdf_file): try: pdf_path = pdf_file.name if pdf_file else "wifi_basics_teaching_genspark.pdf" assert os.path.exists(pdf_path), f"File not found: {pdf_path}" page_inpaint_colors = { 0: (255, 255, 255), 1: (0, 0, 0) } with tempfile.TemporaryDirectory() as tmpdir: images = convert_from_path(pdf_path, dpi=300, output_folder=tmpdir, fmt="png") output_images = [] for i, img in enumerate(images): np_img = np.array(img)[:, :, ::-1] bbox = expand_bbox(default_bbox, expand_factor=0.3) color = page_inpaint_colors.get(i, (255, 255, 255)) inpainted = inpaint_image(np_img, bbox, color=color) img_path = os.path.join(tmpdir, f"page_{i}.png") cv2.imwrite(img_path, inpainted) output_images.append(img_path) temp_pdf_path = os.path.join(tmpdir, "inpainted_output.pdf") with open(temp_pdf_path, "wb") as f: f.write(img2pdf.convert([Path(p) for p in sorted(output_images)])) # Save to persistent path final_pdf_path = f"inpainted_output_{uuid.uuid4().hex[:8]}.pdf" shutil.copy(temp_pdf_path, final_pdf_path) return final_pdf_path except Exception as e: print(f"❌ Error during PDF processing: {e}") return None # Gradio UI with gr.Blocks() as demo: gr.Markdown("### 🧽 PDF Logo Inpainting (Solid Fill, Expand + Color Config)") with gr.Row(): pdf_input = gr.File( label="Upload PDF (or leave empty to use test.pdf)", file_types=[".pdf"], interactive=True ) pdf_output = gr.File(label="Download Inpainted PDF") run_button = gr.Button("Process and Inpaint") run_button.click(fn=process_pdf, inputs=pdf_input, outputs=pdf_output) demo.launch()