STLooo commited on
Commit
5085139
·
verified ·
1 Parent(s): 9034905

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -21
app.py CHANGED
@@ -11,34 +11,48 @@ TARGET_WIDTH, TARGET_HEIGHT = 2133, 1200
11
  POS1 = (1032, 0)
12
  POS2 = (4666, 0)
13
 
14
- # 建立資料夾
15
  def ensure_dir(path):
16
  os.makedirs(path, exist_ok=True)
17
  if not os.access(path, os.W_OK):
18
  raise RuntimeError(f"❌ 無法寫入:{path}")
19
  ensure_dir(OUTPUT_DIR)
20
 
21
- # PDF 轉圖片
22
- def pdf_to_images(pdf_file):
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  images = []
24
  with fitz.open(pdf_file.name) as doc:
25
- for page in doc:
 
 
26
  pix = page.get_pixmap(matrix=fitz.Matrix(2, 2), colorspace=fitz.csRGB)
27
  img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
28
  images.append(img)
29
  return images
30
 
31
- # 合成邏輯
32
  def overlay_image(bg, fg_img, x, y):
33
- fg = fg_img.resize((TARGET_WIDTH, TARGET_HEIGHT), resample=Image.BILINEAR)
34
- fg = np.array(fg)
35
- bg[y:y+TARGET_HEIGHT, x:x+TARGET_WIDTH] = fg[:, :, :3]
36
  return bg
37
 
38
- # 處理流程
39
  def process_and_combine(images, prefix):
40
- bg_pil = Image.open(BG_PATH).convert("RGB")
41
- bg = np.array(bg_pil)
 
42
 
43
  for f in os.listdir(OUTPUT_DIR):
44
  if f.endswith(".jpg"):
@@ -49,7 +63,7 @@ def process_and_combine(images, prefix):
49
  combined = overlay_image(bg.copy(), img, *POS1)
50
  combined = overlay_image(combined, img, *POS2)
51
  output_path = os.path.join(OUTPUT_DIR, f"{prefix}{i:03d}.jpg")
52
- cv2.imwrite(output_path, cv2.cvtColor(combined, cv2.COLOR_RGB2BGR))
53
  results.append((output_path, f"{prefix}{i:03d}"))
54
  if i % 10 == 0:
55
  gc.collect()
@@ -61,16 +75,18 @@ def process_and_combine(images, prefix):
61
  for f in sorted(os.listdir(OUTPUT_DIR)):
62
  if f.endswith(".jpg"):
63
  zipf.write(os.path.join(OUTPUT_DIR, f), arcname=f)
64
- return results, ZIP_PATH, f"✅ 共合成 {len(results)} 張圖,已打包 ZIP"
65
 
66
- # 主流程
67
- def process_inputs(file_list, prefix):
 
 
68
  prefix = prefix.strip() or "result_"
 
69
  images = []
70
- for file in file_list:
71
  name = file.name.lower()
72
  if name.endswith(".pdf"):
73
- images.extend(pdf_to_images(file))
74
  elif name.endswith((".png", ".jpg", ".jpeg")):
75
  img = Image.open(file).convert("RGB")
76
  images.append(img)
@@ -78,20 +94,21 @@ def process_inputs(file_list, prefix):
78
  raise gr.Error(f"不支援的檔案格式:{name}")
79
  return process_and_combine(images, prefix)
80
 
81
- # UI
82
  demo = gr.Interface(
83
  fn=process_inputs,
84
  inputs=[
85
  gr.Files(label="📎 上傳 PDF 或圖片", file_types=[".pdf", ".png", ".jpg", ".jpeg"]),
86
- gr.Textbox(label="檔名前綴(可選)", placeholder="例如:poster_")
 
87
  ],
88
  outputs=[
89
  gr.Gallery(label="🖼️ 預覽", columns=3, height="auto"),
90
  gr.File(label="⬇️ 下載 ZIP"),
91
- gr.Textbox(label="📄 日誌")
92
  ],
93
  title="PDF 圖片合成工具",
94
- description="📄🖼️ 將 PDF 或圖片套用背景合成為圖,背景為固定寬度 7872x1200。"
95
  )
96
 
97
  if __name__ == "__main__":
 
11
  POS1 = (1032, 0)
12
  POS2 = (4666, 0)
13
 
 
14
  def ensure_dir(path):
15
  os.makedirs(path, exist_ok=True)
16
  if not os.access(path, os.W_OK):
17
  raise RuntimeError(f"❌ 無法寫入:{path}")
18
  ensure_dir(OUTPUT_DIR)
19
 
20
+ # 解析頁碼範圍字串(如 "1-3,5,7")
21
+ def parse_page_range(range_str):
22
+ if not range_str.strip():
23
+ return None
24
+ pages = set()
25
+ for part in range_str.split(","):
26
+ if '-' in part:
27
+ start, end = map(int, part.split("-"))
28
+ pages.update(range(start, end + 1))
29
+ else:
30
+ pages.add(int(part))
31
+ return sorted(pages)
32
+
33
+ # PDF轉圖片
34
+ def pdf_to_images(pdf_file, selected_pages=None):
35
  images = []
36
  with fitz.open(pdf_file.name) as doc:
37
+ for i, page in enumerate(doc, 1):
38
+ if selected_pages and i not in selected_pages:
39
+ continue
40
  pix = page.get_pixmap(matrix=fitz.Matrix(2, 2), colorspace=fitz.csRGB)
41
  img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
42
  images.append(img)
43
  return images
44
 
45
+ # 合成圖片
46
  def overlay_image(bg, fg_img, x, y):
47
+ fg = cv2.resize(np.array(fg_img), (TARGET_WIDTH, TARGET_HEIGHT), interpolation=cv2.INTER_AREA)
48
+ bg[y:y+TARGET_HEIGHT, x:x+TARGET_WIDTH] = fg
 
49
  return bg
50
 
51
+ # 處理與合成流程
52
  def process_and_combine(images, prefix):
53
+ bg = cv2.imread(BG_PATH)
54
+ if bg is None:
55
+ raise gr.Error("❌ 無法讀取 background.jpg")
56
 
57
  for f in os.listdir(OUTPUT_DIR):
58
  if f.endswith(".jpg"):
 
63
  combined = overlay_image(bg.copy(), img, *POS1)
64
  combined = overlay_image(combined, img, *POS2)
65
  output_path = os.path.join(OUTPUT_DIR, f"{prefix}{i:03d}.jpg")
66
+ cv2.imwrite(output_path, combined)
67
  results.append((output_path, f"{prefix}{i:03d}"))
68
  if i % 10 == 0:
69
  gc.collect()
 
75
  for f in sorted(os.listdir(OUTPUT_DIR)):
76
  if f.endswith(".jpg"):
77
  zipf.write(os.path.join(OUTPUT_DIR, f), arcname=f)
 
78
 
79
+ return results, ZIP_PATH, f"✅ 成功合成 {len(results)} 張圖,已打包 ZIP"
80
+
81
+ # 主邏輯:上傳處理
82
+ def process_inputs(files, prefix, page_range):
83
  prefix = prefix.strip() or "result_"
84
+ selected_pages = parse_page_range(page_range)
85
  images = []
86
+ for file in files:
87
  name = file.name.lower()
88
  if name.endswith(".pdf"):
89
+ images.extend(pdf_to_images(file, selected_pages))
90
  elif name.endswith((".png", ".jpg", ".jpeg")):
91
  img = Image.open(file).convert("RGB")
92
  images.append(img)
 
94
  raise gr.Error(f"不支援的檔案格式:{name}")
95
  return process_and_combine(images, prefix)
96
 
97
+ # Gradio UI
98
  demo = gr.Interface(
99
  fn=process_inputs,
100
  inputs=[
101
  gr.Files(label="📎 上傳 PDF 或圖片", file_types=[".pdf", ".png", ".jpg", ".jpeg"]),
102
+ gr.Textbox(label="檔名前綴(可選)", placeholder="例如:poster_"),
103
+ gr.Textbox(label="選擇頁碼(PDF):例如 1-3,5,7,留空表示全部", placeholder="1-5,7")
104
  ],
105
  outputs=[
106
  gr.Gallery(label="🖼️ 預覽", columns=3, height="auto"),
107
  gr.File(label="⬇️ 下載 ZIP"),
108
+ gr.Textbox(label="📄 處理日誌")
109
  ],
110
  title="PDF 圖片合成工具",
111
+ description="📄🖼️ 將 PDF 或圖片套用固定背景合成為圖,背景為 7872x1200,支援 PDF 選擇頁數與多檔處理。"
112
  )
113
 
114
  if __name__ == "__main__":