awacke1 commited on
Commit
746b7cb
·
verified ·
1 Parent(s): 87e82bc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -20
app.py CHANGED
@@ -18,9 +18,9 @@ st.set_page_config(
18
  initial_sidebar_state="expanded",
19
  )
20
 
21
- st.title("🖼️ Image → PDF • Full-Page Layout Generator")
22
  st.markdown(
23
- "Upload images, filter by orientation, reorder visually, and generate a PDF with each image filling its own page."
24
  )
25
 
26
  # --- Sidebar: Page Settings -----------------------------
@@ -52,7 +52,6 @@ st.header("2️⃣ Upload, Filter & Reorder Images")
52
  uploaded = st.file_uploader(
53
  "📂 Select PNG/JPG images", type=["png","jpg","jpeg"], accept_multiple_files=True
54
  )
55
-
56
  ordered_files = []
57
  if uploaded:
58
  records = []
@@ -70,21 +69,16 @@ if uploaded:
70
  "order": idx
71
  })
72
  df = pd.DataFrame(records)
73
-
74
  dims = st.sidebar.multiselect(
75
  "Include orientations:", options=["Landscape","Portrait","Square"],
76
  default=["Landscape","Portrait","Square"]
77
  )
78
  df = df[df["orientation"].isin(dims)].reset_index(drop=True)
79
-
80
  st.markdown("#### Image Metadata")
81
  st.dataframe(df.style.format({"aspect_ratio": "{:.2f}"}), use_container_width=True)
82
-
83
  st.markdown("#### Reorder Panels")
84
  try:
85
- edited = st.experimental_data_editor(
86
- df, num_rows="fixed", use_container_width=True
87
- )
88
  ordered_df = edited
89
  except Exception:
90
  edited = st.data_editor(
@@ -98,11 +92,10 @@ if uploaded:
98
  use_container_width=True,
99
  )
100
  ordered_df = edited.sort_values("order").reset_index(drop=True)
101
-
102
  name2file = {f.name: f for f in uploaded}
103
  ordered_files = [name2file[n] for n in ordered_df["filename"] if n in name2file]
104
 
105
- # --- PDF Creation Logic ----------------------------------
106
  def top_n_words(names, n=5):
107
  words = []
108
  for fn in names:
@@ -110,33 +103,70 @@ def top_n_words(names, n=5):
110
  words += re.findall(r"\w+", stem.lower())
111
  return [w for w,_ in Counter(words).most_common(n)]
112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
 
 
114
  def make_fullpage_pdf(images, w_pt, h_pt):
115
  buf = io.BytesIO()
116
- c = canvas.Canvas(buf, pagesize=(w_pt, h_ht := h_pt))
117
  for f in images:
118
  im = Image.open(f)
119
  iw, ih = im.size
120
- # calculate scale to fit page
121
  scale = min(w_pt/iw, h_pt/ih)
122
- new_w = int(iw * scale)
123
- new_h = int(ih * scale)
124
  x = (w_pt - new_w)/2
125
  y = (h_pt - new_h)/2
126
- im = im.resize((new_w, new_h), Image.LANCZOS)
127
  c.drawImage(ImageReader(im), x, y, new_w, new_h, preserveAspectRatio=False, mask='auto')
128
  c.showPage()
129
- c.save()
130
- buf.seek(0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  return buf.getvalue()
132
 
133
  # --- Generate & Download -------------------------------
134
  st.header("3️⃣ Generate & Download PDF")
135
- if st.button("🎉 Generate PDF"):
 
 
 
 
 
136
  if not ordered_files:
137
  st.warning("Upload and reorder at least one image.")
138
  else:
139
- date_s = datetime.now().strftime("%Y-%m%d")
140
  words = top_n_words([f.name for f in ordered_files])
141
  slug = "-".join(words)
142
  fname = f"{date_s}-{slug}.pdf"
@@ -152,6 +182,27 @@ if st.button("🎉 Generate PDF"):
152
  except:
153
  st.info("Install `pymupdf` for preview.")
154
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  # --- Footer ------------------------------------------------
156
  st.sidebar.markdown("---")
157
  st.sidebar.markdown("Built by Aaron C. Wacker • Senior AI Engineer")
 
18
  initial_sidebar_state="expanded",
19
  )
20
 
21
+ st.title("🖼️ Image → PDF • Full-Page & Custom Layout Generator")
22
  st.markdown(
23
+ "Upload images, filter by orientation, reorder visually, and generate PDFs with various layouts."
24
  )
25
 
26
  # --- Sidebar: Page Settings -----------------------------
 
52
  uploaded = st.file_uploader(
53
  "📂 Select PNG/JPG images", type=["png","jpg","jpeg"], accept_multiple_files=True
54
  )
 
55
  ordered_files = []
56
  if uploaded:
57
  records = []
 
69
  "order": idx
70
  })
71
  df = pd.DataFrame(records)
 
72
  dims = st.sidebar.multiselect(
73
  "Include orientations:", options=["Landscape","Portrait","Square"],
74
  default=["Landscape","Portrait","Square"]
75
  )
76
  df = df[df["orientation"].isin(dims)].reset_index(drop=True)
 
77
  st.markdown("#### Image Metadata")
78
  st.dataframe(df.style.format({"aspect_ratio": "{:.2f}"}), use_container_width=True)
 
79
  st.markdown("#### Reorder Panels")
80
  try:
81
+ edited = st.experimental_data_editor(df, num_rows="fixed", use_container_width=True)
 
 
82
  ordered_df = edited
83
  except Exception:
84
  edited = st.data_editor(
 
92
  use_container_width=True,
93
  )
94
  ordered_df = edited.sort_values("order").reset_index(drop=True)
 
95
  name2file = {f.name: f for f in uploaded}
96
  ordered_files = [name2file[n] for n in ordered_df["filename"] if n in name2file]
97
 
98
+ # --- Utility: Word extraction --------------------------
99
  def top_n_words(names, n=5):
100
  words = []
101
  for fn in names:
 
103
  words += re.findall(r"\w+", stem.lower())
104
  return [w for w,_ in Counter(words).most_common(n)]
105
 
106
+ def first_n_words_ordered(names, n=5):
107
+ words = []
108
+ for fn in names:
109
+ stem = os.path.splitext(fn)[0]
110
+ tokens = re.findall(r"\w+", stem)
111
+ for t in tokens:
112
+ if len(words) < n:
113
+ words.append(t)
114
+ else:
115
+ break
116
+ if len(words) >= n:
117
+ break
118
+ return words
119
 
120
+ # --- PDF Creation: Full Page ----------------------------
121
  def make_fullpage_pdf(images, w_pt, h_pt):
122
  buf = io.BytesIO()
123
+ c = canvas.Canvas(buf, pagesize=(w_pt, h_pt))
124
  for f in images:
125
  im = Image.open(f)
126
  iw, ih = im.size
 
127
  scale = min(w_pt/iw, h_pt/ih)
128
+ new_w, new_h = iw*scale, ih*scale
 
129
  x = (w_pt - new_w)/2
130
  y = (h_pt - new_h)/2
131
+ im = im.resize((int(new_w), int(new_h)), Image.LANCZOS)
132
  c.drawImage(ImageReader(im), x, y, new_w, new_h, preserveAspectRatio=False, mask='auto')
133
  c.showPage()
134
+ c.save(); buf.seek(0)
135
+ return buf.getvalue()
136
+
137
+ # --- PDF Creation: Image-sized + Captions --------------
138
+ def make_image_sized_pdf(images):
139
+ buf = io.BytesIO()
140
+ c = canvas.Canvas(buf)
141
+ for f in images:
142
+ im = Image.open(f)
143
+ iw, ih = im.size
144
+ # set page to image dims + caption space
145
+ cap_h = 20
146
+ page_w, page_h = iw, ih + cap_h
147
+ c.setPageSize((page_w, page_h))
148
+ # draw image
149
+ c.drawImage(ImageReader(im), 0, cap_h, iw, ih, preserveAspectRatio=True, mask='auto')
150
+ # caption
151
+ caption = os.path.splitext(f.name)[0]
152
+ c.setFont("Helvetica", 12)
153
+ c.drawCentredString(page_w/2, cap_h/2, caption)
154
+ c.showPage()
155
+ c.save(); buf.seek(0)
156
  return buf.getvalue()
157
 
158
  # --- Generate & Download -------------------------------
159
  st.header("3️⃣ Generate & Download PDF")
160
+ # Full-page button
161
+ def build_timestamp(prefix_time=False):
162
+ fmt = "%Y-%m%d-%I%M%p" if prefix_time else "%Y-%m%d"
163
+ return datetime.now().strftime(fmt)
164
+
165
+ if st.button("🎉 Generate Full-Page PDF"):
166
  if not ordered_files:
167
  st.warning("Upload and reorder at least one image.")
168
  else:
169
+ date_s = build_timestamp()
170
  words = top_n_words([f.name for f in ordered_files])
171
  slug = "-".join(words)
172
  fname = f"{date_s}-{slug}.pdf"
 
182
  except:
183
  st.info("Install `pymupdf` for preview.")
184
 
185
+ # Custom-sized + captions button
186
+ if st.button("🖋️ Generate Image-Sized PDF with Captions"):
187
+ if not ordered_files:
188
+ st.warning("Upload and reorder at least one image.")
189
+ else:
190
+ date_s = build_timestamp(prefix_time=True)
191
+ words = first_n_words_ordered([f.name for f in ordered_files])
192
+ slug = "-".join(words)
193
+ fname = f"{date_s}-{slug}.pdf"
194
+ pdf = make_image_sized_pdf(ordered_files)
195
+ st.success(f"✅ PDF ready: **{fname}**")
196
+ st.download_button("⬇️ Download PDF", data=pdf, file_name=fname, mime="application/pdf")
197
+ st.markdown("#### Preview")
198
+ try:
199
+ import fitz
200
+ doc = fitz.open(stream=pdf, filetype="pdf")
201
+ pix = doc[0].get_pixmap(matrix=fitz.Matrix(1.5,1.5))
202
+ st.image(pix.tobytes(), use_container_width=True)
203
+ except:
204
+ st.info("Install `pymupdf` for preview.")
205
+
206
  # --- Footer ------------------------------------------------
207
  st.sidebar.markdown("---")
208
  st.sidebar.markdown("Built by Aaron C. Wacker • Senior AI Engineer")