Create thumbnail grid from slide images with optional placeholder outlining.
(
image_paths,
cols,
width,
start_slide_num=0,
placeholder_regions=None,
slide_dimensions=None,
)
| 319 | |
| 320 | |
| 321 | def create_grid( |
| 322 | image_paths, |
| 323 | cols, |
| 324 | width, |
| 325 | start_slide_num=0, |
| 326 | placeholder_regions=None, |
| 327 | slide_dimensions=None, |
| 328 | ): |
| 329 | """Create thumbnail grid from slide images with optional placeholder outlining.""" |
| 330 | font_size = int(width * FONT_SIZE_RATIO) |
| 331 | label_padding = int(font_size * LABEL_PADDING_RATIO) |
| 332 | |
| 333 | # Get dimensions |
| 334 | with Image.open(image_paths[0]) as img: |
| 335 | aspect = img.height / img.width |
| 336 | height = int(width * aspect) |
| 337 | |
| 338 | # Calculate grid size |
| 339 | rows = (len(image_paths) + cols - 1) // cols |
| 340 | grid_w = cols * width + (cols + 1) * GRID_PADDING |
| 341 | grid_h = rows * (height + font_size + label_padding * 2) + (rows + 1) * GRID_PADDING |
| 342 | |
| 343 | # Create grid |
| 344 | grid = Image.new("RGB", (grid_w, grid_h), "white") |
| 345 | draw = ImageDraw.Draw(grid) |
| 346 | |
| 347 | # Load font with size based on thumbnail width |
| 348 | try: |
| 349 | # Use Pillow's default font with size |
| 350 | font = ImageFont.load_default(size=font_size) |
| 351 | except Exception: |
| 352 | # Fall back to basic default font if size parameter not supported |
| 353 | font = ImageFont.load_default() |
| 354 | |
| 355 | # Place thumbnails |
| 356 | for i, img_path in enumerate(image_paths): |
| 357 | row, col = i // cols, i % cols |
| 358 | x = col * width + (col + 1) * GRID_PADDING |
| 359 | y_base = ( |
| 360 | row * (height + font_size + label_padding * 2) + (row + 1) * GRID_PADDING |
| 361 | ) |
| 362 | |
| 363 | # Add label with actual slide number |
| 364 | label = f"{start_slide_num + i}" |
| 365 | bbox = draw.textbbox((0, 0), label, font=font) |
| 366 | text_w = bbox[2] - bbox[0] |
| 367 | draw.text( |
| 368 | (x + (width - text_w) // 2, y_base + label_padding), |
| 369 | label, |
| 370 | fill="black", |
| 371 | font=font, |
| 372 | ) |
| 373 | |
| 374 | # Add thumbnail below label with proportional spacing |
| 375 | y_thumbnail = y_base + label_padding + font_size + label_padding |
| 376 | |
| 377 | with Image.open(img_path) as img: |
| 378 | # Get original dimensions before thumbnail |