Spaces:
Running
Running
| import gradio as gr | |
| from PIL import Image, ImageChops | |
| import img2pdf | |
| import io | |
| # --- 核心逻辑 (复用之前的代码) --- | |
| def trim_whitespace(im, fuzz_level=20): | |
| bg = Image.new(im.mode, im.size, (255, 255, 255)) | |
| diff = ImageChops.difference(im, bg) | |
| diff = ImageChops.add(diff, diff, 1, -fuzz_level) | |
| bbox = diff.getbbox() | |
| if bbox: | |
| return im.crop(bbox) | |
| return im | |
| def process_pipeline(files, quality, fuzz_level, progress=gr.Progress()): | |
| if not files: return None | |
| pdf_components = [] | |
| for filepath in progress.tqdm(files, desc="处理中"): | |
| try: | |
| with Image.open(filepath) as img: | |
| if img.mode in ('RGBA', 'LA') or (img.mode == 'P' and 'transparency' in img.info): | |
| bg = Image.new('RGB', img.size, (255, 255, 255)) | |
| if img.mode!= 'RGBA': img = img.convert('RGBA') | |
| bg.paste(img, mask=img.split()[3]) | |
| img = bg | |
| else: | |
| img = img.convert('RGB') | |
| trimmed = trim_whitespace(img, fuzz_level) | |
| byte_arr = io.BytesIO() | |
| trimmed.save(byte_arr, format='JPEG', quality=int(quality)) | |
| pdf_components.append(byte_arr.getvalue()) | |
| except Exception: continue | |
| if not pdf_components: return None | |
| output_filename = "output_document.pdf" | |
| with open(output_filename, "wb") as f: | |
| f.write(img2pdf.convert(pdf_components)) | |
| return output_filename | |
| # --- 模块化 UI 接口 --- | |
| def create_ui(): | |
| """ | |
| 每个工具模块都需要暴露这个函数。 | |
| 注意:不要在这里创建 gr.Blocks(),直接写 Row/Column 即可, | |
| 因为它们会被嵌入到主程序的 Tab 中。 | |
| """ | |
| with gr.Row(): | |
| with gr.Column(): | |
| file_input = gr.File(file_count="multiple", file_types=["image"], label="上传图片") | |
| quality = gr.Slider(10, 100, 90, label="质量") | |
| fuzz = gr.Slider(0, 100, 30, label="容差") | |
| btn = gr.Button("开始处理", variant="primary") | |
| with gr.Column(): | |
| output = gr.File(label="下载 PDF") | |
| btn.click(process_pipeline, [file_input, quality, fuzz], output) | |