Preeeeet commited on
Commit
fd21ec3
·
verified ·
1 Parent(s): f576f2c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -85
app.py CHANGED
@@ -16,7 +16,6 @@ from datetime import datetime
16
  pillow_heif.register_heif_opener()
17
 
18
  # --- CONSTANTS & LAYOUT ---
19
- # Page: Letter 8.5" x 11", margins below
20
  CONTENT_WIDTH_IN = 8.5 - (0.5 + 0.5) # 7.5" total content width
21
 
22
  JOB_MAP = {
@@ -137,7 +136,6 @@ def generate_report(image_items, job_details, compress_images, quality, progress
137
  # Header
138
  header = section.header
139
  header_table = header.add_table(rows=1, cols=2, width=Inches(CONTENT_WIDTH_IN))
140
- header_table.autofit = False
141
  set_table_fixed_layout(header_table)
142
  header_table.columns[0].width = Inches(2.5)
143
  header_table.columns[1].width = Inches(CONTENT_WIDTH_IN - 2.5)
@@ -161,108 +159,95 @@ def generate_report(image_items, job_details, compress_images, quality, progress
161
  footer = section.footer
162
  add_page_number(footer.paragraphs[0])
163
 
164
- # --- LAYOUT CHANGE: 2x2 GRID (4 PHOTOS PER PAGE) ---
165
  num_images = len(image_items)
166
  processed = 0
167
 
168
- for start in range(0, num_images, 4): # Process 4 images at a time
169
  if start > 0:
170
  doc.add_page_break()
171
 
172
  page_items = image_items[start:start + 4]
173
 
174
- # A 2x4 table holds two (Desc | Photo) pairs per row
175
- page_table = doc.add_table(rows=2, cols=4)
176
  page_table.width = Inches(CONTENT_WIDTH_IN)
177
- page_table.autofit = False
178
  set_table_fixed_layout(page_table)
179
  page_table.style = 'Table Grid'
180
  page_table.alignment = WD_TABLE_ALIGNMENT.CENTER
181
 
182
- # Define column widths for the new grid layout
183
- PAIR_WIDTH_IN = CONTENT_WIDTH_IN / 2.0
184
- DESC_COL_IN_GRID = PAIR_WIDTH_IN * (1 / 5.0)
185
- PHOTO_COL_IN_GRID = PAIR_WIDTH_IN * (4 / 5.0)
186
 
187
- # Lock column widths
188
- page_table.columns[0].width = Inches(DESC_COL_IN_GRID)
189
- page_table.columns[1].width = Inches(PHOTO_COL_IN_GRID)
190
- page_table.columns[2].width = Inches(DESC_COL_IN_GRID)
191
- page_table.columns[3].width = Inches(PHOTO_COL_IN_GRID)
192
-
193
- # Define row heights to split the page
194
- ROW_HEIGHT_GRID_IN = 4.4 # Height for each of the two main rows
195
-
196
- # Lock row heights
197
- for r in page_table.rows:
198
- r.height = Inches(ROW_HEIGHT_GRID_IN)
199
- r.height_rule = WD_ROW_HEIGHT_RULE.EXACTLY
200
-
201
- # Clean all cells before populating
202
  for row in page_table.rows:
203
- for cell in row.cells:
204
- ensure_cell_has_one_empty_paragraph(cell)
205
-
206
- # Loop through the up-to-4 items for this page and place them in the grid
207
- for item_idx, item in enumerate(page_items):
208
- row_idx = item_idx // 2 # Item 0,1 -> row 0. Item 2,3 -> row 1.
209
- pair_idx = item_idx % 2 # Item 0,2 -> pair 0. Item 1,3 -> pair 1.
210
-
211
- desc_col_idx = pair_idx * 2
212
- photo_col_idx = desc_col_idx + 1
213
-
214
- desc_cell = page_table.cell(row_idx, desc_col_idx)
215
- photo_cell = page_table.cell(row_idx, photo_col_idx)
216
-
217
- desc_cell.vertical_alignment = WD_ALIGN_VERTICAL.TOP
218
- photo_cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
219
-
220
- rotation = item.get('rotation', 0) or 0
221
-
222
- # Description
223
- p_desc = desc_cell.paragraphs[0]
224
- run_label = p_desc.add_run("Description:\n")
225
- run_label.bold = True
226
- p_desc.add_run(item.get('description', '') or '')
227
-
228
- # Photo Sizing and Placement
229
- PHOTO_MAX_W_IN_GRID = PHOTO_COL_IN_GRID - 0.15
230
- PHOTO_MAX_H_IN_GRID = ROW_HEIGHT_GRID_IN - 0.15
231
-
232
- try:
233
- item['file'].seek(0)
234
- im = Image.open(item['file'])
235
- if rotation:
236
- im = im.rotate(rotation, expand=True)
237
- w_px, h_px = im.size
238
- except Exception:
239
- w_px, h_px = (1000, 1000)
240
-
241
- img_ratio = (w_px / h_px) if h_px else 1.0
242
- box_ratio = PHOTO_MAX_W_IN_GRID / PHOTO_MAX_H_IN_GRID
243
-
244
- img_stream = process_image(
245
- item['file'], compress=compress_images, quality=quality, rotation=rotation
246
- )
247
-
248
- if img_stream:
249
- p_photo = photo_cell.paragraphs[0]
250
- p_photo.alignment = WD_ALIGN_PARAGRAPH.CENTER
251
- if img_ratio >= box_ratio:
252
- p_photo.add_run().add_picture(img_stream, width=Inches(PHOTO_MAX_W_IN_GRID))
253
- else:
254
- p_photo.add_run().add_picture(img_stream, height=Inches(PHOTO_MAX_H_IN_GRID))
255
-
256
- processed += 1
257
- if num_images:
258
- progress_bar.progress(processed / num_images)
 
259
 
260
  # Save DOCX
261
  doc_io = io.BytesIO()
262
  doc.save(doc_io)
263
  doc_io.seek(0)
264
 
265
- # Optional PDF conversion via LibreOffice
266
  pdf_io = None
267
  try:
268
  with open("temp_report.docx", "wb") as f:
@@ -393,5 +378,4 @@ if generate_button:
393
  c2.download_button("⬇️ Download PDF (.pdf)", pdf_io, f"{file_base}.pdf", use_container_width=True)
394
  except Exception as e:
395
  st.error(f"A critical error occurred: {e}")
396
- progress_bar.empty()
397
-
 
16
  pillow_heif.register_heif_opener()
17
 
18
  # --- CONSTANTS & LAYOUT ---
 
19
  CONTENT_WIDTH_IN = 8.5 - (0.5 + 0.5) # 7.5" total content width
20
 
21
  JOB_MAP = {
 
136
  # Header
137
  header = section.header
138
  header_table = header.add_table(rows=1, cols=2, width=Inches(CONTENT_WIDTH_IN))
 
139
  set_table_fixed_layout(header_table)
140
  header_table.columns[0].width = Inches(2.5)
141
  header_table.columns[1].width = Inches(CONTENT_WIDTH_IN - 2.5)
 
159
  footer = section.footer
160
  add_page_number(footer.paragraphs[0])
161
 
162
+ # --- LAYOUT FIX: TRUE 2x2 GRID (4 PHOTOS PER PAGE) ---
163
  num_images = len(image_items)
164
  processed = 0
165
 
166
+ for start in range(0, num_images, 4): # Process 4 images per page
167
  if start > 0:
168
  doc.add_page_break()
169
 
170
  page_items = image_items[start:start + 4]
171
 
172
+ # Create a true 2x2 table for the grid
173
+ page_table = doc.add_table(rows=2, cols=2)
174
  page_table.width = Inches(CONTENT_WIDTH_IN)
 
175
  set_table_fixed_layout(page_table)
176
  page_table.style = 'Table Grid'
177
  page_table.alignment = WD_TABLE_ALIGNMENT.CENTER
178
 
179
+ # Define dimensions for each cell in the 2x2 grid
180
+ COL_WIDTH_GRID_IN = CONTENT_WIDTH_IN / 2.0
181
+ ROW_HEIGHT_GRID_IN = 4.4 # Height for each of the two rows
 
182
 
183
+ # Set column widths and row heights
184
+ for col in page_table.columns:
185
+ col.width = Inches(COL_WIDTH_GRID_IN)
 
 
 
 
 
 
 
 
 
 
 
 
186
  for row in page_table.rows:
187
+ row.height = Inches(ROW_HEIGHT_GRID_IN)
188
+ row.height_rule = WD_ROW_HEIGHT_RULE.EXACTLY
189
+
190
+ # Loop through the grid cells and populate them
191
+ item_idx_on_page = 0
192
+ for row_idx in range(2):
193
+ for col_idx in range(2):
194
+ # Check if there is an image for this cell
195
+ if item_idx_on_page < len(page_items):
196
+ item = page_items[item_idx_on_page]
197
+ cell = page_table.cell(row_idx, col_idx)
198
+ ensure_cell_has_one_empty_paragraph(cell)
199
+ cell.vertical_alignment = WD_ALIGN_VERTICAL.TOP
200
+
201
+ # Add description to the first paragraph
202
+ p_desc = cell.paragraphs[0]
203
+ p_desc.paragraph_format.space_after = Pt(6) # Add space after description
204
+ run_label = p_desc.add_run("Description:\n")
205
+ run_label.bold = True
206
+ p_desc.add_run(item.get('description', '') or '')
207
+
208
+ # Photo Sizing and Placement
209
+ PHOTO_MAX_W_IN_GRID = COL_WIDTH_GRID_IN - 0.2
210
+ # Roughly account for description text height
211
+ PHOTO_MAX_H_IN_GRID = ROW_HEIGHT_GRID_IN - 0.8
212
+
213
+ rotation = item.get('rotation', 0) or 0
214
+ try:
215
+ item['file'].seek(0)
216
+ im = Image.open(item['file'])
217
+ if rotation:
218
+ im = im.rotate(rotation, expand=True)
219
+ w_px, h_px = im.size
220
+ except Exception:
221
+ w_px, h_px = (1000, 1000)
222
+
223
+ img_ratio = (w_px / h_px) if h_px else 1.0
224
+ box_ratio = PHOTO_MAX_W_IN_GRID / PHOTO_MAX_H_IN_GRID
225
+
226
+ img_stream = process_image(
227
+ item['file'], compress=compress_images, quality=quality, rotation=rotation
228
+ )
229
+
230
+ if img_stream:
231
+ # Add a new paragraph in the same cell for the photo
232
+ p_photo = cell.add_paragraph()
233
+ p_photo.alignment = WD_ALIGN_PARAGRAPH.CENTER
234
+ if img_ratio >= box_ratio:
235
+ p_photo.add_run().add_picture(img_stream, width=Inches(PHOTO_MAX_W_IN_GRID))
236
+ else:
237
+ p_photo.add_run().add_picture(img_stream, height=Inches(PHOTO_MAX_H_IN_GRID))
238
+
239
+ processed += 1
240
+ if num_images:
241
+ progress_bar.progress(processed / num_images)
242
+
243
+ item_idx_on_page += 1
244
 
245
  # Save DOCX
246
  doc_io = io.BytesIO()
247
  doc.save(doc_io)
248
  doc_io.seek(0)
249
 
250
+ # Optional PDF conversion
251
  pdf_io = None
252
  try:
253
  with open("temp_report.docx", "wb") as f:
 
378
  c2.download_button("⬇️ Download PDF (.pdf)", pdf_io, f"{file_base}.pdf", use_container_width=True)
379
  except Exception as e:
380
  st.error(f"A critical error occurred: {e}")
381
+ progress_bar.empty()