Spaces:
Sleeping
Sleeping
File size: 4,465 Bytes
8f796ba 716d72a 8f796ba d3329bf e3ae23b d3329bf 716d72a d3329bf 716d72a 8f796ba 716d72a 94182ca 716d72a 5632e3e 5085139 f1926db 5085139 f1926db 5085139 f1926db 5085139 f1926db 5085139 f1926db 8f796ba e3ae23b 75b73d9 f1926db 8f796ba 5632e3e 5085139 8f796ba f1926db 5085139 d3329bf 5085139 8f796ba 5085139 ea494fa 716d72a 5e6e8d3 716d72a 8f796ba 5085139 8f796ba 716d72a 94182ca 716d72a 8f796ba 716d72a 5085139 f1926db 8f796ba f1926db 8f796ba 5085139 8f796ba 716d72a 5085139 94182ca e72a030 f1926db 8f796ba 716d72a f1926db 8f796ba 5632e3e f1926db e3ae23b e72a030 e3ae23b e72a030 5085139 f1926db e3ae23b 5085139 e3ae23b 5085139 e3ae23b d3329bf 94182ca | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | import os, cv2, zipfile, gc, gradio as gr
import numpy as np
import fitz # PyMuPDF
from PIL import Image
# 設定
OUTPUT_DIR = "output"
ZIP_PATH = os.path.join(OUTPUT_DIR, "results.zip")
BG_PATH = "background.jpg"
TARGET_WIDTH, TARGET_HEIGHT = 2133, 1200
POS1 = (1032, 0)
POS2 = (4666, 0)
def ensure_dir(path):
os.makedirs(path, exist_ok=True)
if not os.access(path, os.W_OK):
raise RuntimeError(f"❌ 無法寫入:{path}")
ensure_dir(OUTPUT_DIR)
# 解析頁碼範圍字串(如 "1-3,5,7")
def parse_page_selection(selection_text):
if not selection_text.strip():
return None
pages = set()
for part in selection_text.split(','):
part = part.strip()
if '-' in part:
start, end = map(int, part.split('-'))
pages.update(range(start, end + 1))
elif part.isdigit():
pages.add(int(part))
return sorted(pages)
# PDF轉圖片(np.array 格式,BGR)
def pdf_to_images(pdf_file, page_list=None):
images = []
with fitz.open(pdf_file.name) as doc:
total_pages = len(doc)
selected = page_list or list(range(1, total_pages + 1))
for page_num in selected:
if 1 <= page_num <= total_pages:
pix = doc[page_num - 1].get_pixmap(matrix=fitz.Matrix(2, 2), colorspace=fitz.csRGB)
img = np.frombuffer(pix.samples, dtype=np.uint8).reshape((pix.height, pix.width, 3))
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
images.append(img)
return images
# 合成圖片
def overlay_image(bg, fg_img, x, y):
fg = cv2.resize(fg_img, (TARGET_WIDTH, TARGET_HEIGHT), interpolation=cv2.INTER_AREA)
bg[y:y+TARGET_HEIGHT, x:x+TARGET_WIDTH] = fg
return bg
# 處理與合成流程
def process_and_combine(images, prefix):
bg = cv2.imread(BG_PATH)
if bg is None:
raise gr.Error("❌ 無法讀取 background.jpg")
for f in os.listdir(OUTPUT_DIR):
if f.endswith(".jpg"):
os.remove(os.path.join(OUTPUT_DIR, f))
results = []
for i, img in enumerate(images, 1):
combined = overlay_image(bg.copy(), img, *POS1)
combined = overlay_image(combined, img, *POS2)
output_path = os.path.join(OUTPUT_DIR, f"{prefix}{i:03d}.jpg")
cv2.imwrite(output_path, combined)
results.append((output_path, f"{prefix}{i:03d}"))
if i % 10 == 0:
gc.collect()
if not results:
raise gr.Error("⚠️ 沒有產生圖片")
with zipfile.ZipFile(ZIP_PATH, "w", zipfile.ZIP_DEFLATED) as zipf:
for f in sorted(os.listdir(OUTPUT_DIR)):
if f.endswith(".jpg"):
zipf.write(os.path.join(OUTPUT_DIR, f), arcname=f)
return results, ZIP_PATH, f"✅ 成功合成 {len(results)} 張圖,已打包 ZIP"
# 主邏輯:上傳處理
def process_inputs(files, prefix, page_selection):
prefix = prefix.strip() or "result_"
selected_pages = parse_page_selection(page_selection)
images = []
for file in files:
name = file.name.lower()
if name.endswith(".pdf"):
images.extend(pdf_to_images(file, selected_pages))
elif name.endswith((".png", ".jpg", ".jpeg")):
img = Image.open(file).convert("RGB")
img = np.array(img)
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
images.append(img)
else:
raise gr.Error(f"不支援的檔案格式:{name}")
if not images:
raise gr.Error("⚠️ 沒有有效圖片可處理,請確認頁碼或檔案內容")
return process_and_combine(images, prefix)
# Gradio UI 元件定義
page_selection = gr.Textbox(label="選擇頁碼(例如:1,3,5-7)", placeholder="留空代表全部頁面")
# 介面建構
demo = gr.Interface(
fn=process_inputs,
inputs=[
gr.Files(label="📎 上傳 PDF 或圖片", file_types=[".pdf", ".png", ".jpg", ".jpeg"]),
gr.Textbox(label="檔名前綴(可選)", placeholder="例如:poster_"),
page_selection
],
outputs=[
gr.Gallery(label="🖼️ 預覽", columns=3, height="auto"),
gr.File(label="⬇️ 下載 ZIP"),
gr.Textbox(label="📄 處理日誌")
],
title="PDF 圖片合成工具",
description="📄🖼️ 將 PDF 或圖片套用固定背景合成為寬圖,背景為 7872x1200,支援 PDF 選擇頁數與多檔處理。"
)
if __name__ == "__main__":
demo.launch() |