Created
October 22, 2025 20:43
-
-
Save J0s3f/5d09838d54b9752b149a30aab269f525 to your computer and use it in GitHub Desktop.
Collagen erstellen aus Fotos im Ordner
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import os | |
| import pillow_heif | |
| from PIL import Image, ImageChops | |
| pillow_heif.register_heif_opener() | |
| directory = 'D:\\fotos\\klein' | |
| output_dir = 'D:\\fotos\\collagen' | |
| canvas_size = 5000 | |
| os.makedirs(output_dir, exist_ok=True) | |
| aspect_threshold = 1.3 | |
| square_images = [] | |
| wide_images = [] | |
| def rotate_and_trim(img, angle=90, bg_color=(255, 255, 255)): | |
| # Bild drehen (expand=True verhindert Abschneiden) | |
| rotated = img.rotate(angle, expand=True) | |
| # Wenn das Bild Transparenz hat → einfacher Fall | |
| if 'A' in rotated.getbands(): | |
| bbox = rotated.getbbox() | |
| return rotated.crop(bbox) | |
| # Wenn kein Alphakanal → über Hintergrundfarbe Differenz berechnen | |
| if bg_color is None: | |
| # Versuchen, Hintergrundfarbe automatisch zu erraten (oben links) | |
| bg_color = rotated.getpixel((0, 0)) | |
| bg = Image.new(rotated.mode, rotated.size, bg_color) | |
| diff = ImageChops.difference(rotated, bg) | |
| bbox = diff.getbbox() | |
| return rotated.crop(bbox) if bbox else rotated | |
| for filename in sorted(os.listdir(directory)): | |
| if not filename.lower().endswith((".jpg", ".jpeg", ".png", ".heic")): | |
| continue | |
| try: | |
| path = os.path.join(directory, filename) | |
| img = Image.open(path) | |
| w, h = img.size | |
| if w < h: | |
| ratio = h / w | |
| else: | |
| ratio = w / h | |
| if ratio > aspect_threshold: | |
| wide_images.append(path) | |
| else: | |
| square_images.append(path) | |
| except Exception as e: | |
| print(f'Fehler bei {filename}: {e}') | |
| print("Es wurden " + str(len(wide_images) + len(square_images)) + " Bilder gefunden") | |
| def resize_with_aspect(img, target_w, target_h): | |
| # Maximale Seite auf target setzen, andere proportional skalieren | |
| w, h = img.size | |
| scale_w = target_w / w | |
| scale_h = target_h / h | |
| if scale_w < scale_h: | |
| # Breite anpassen, Höhe proportional kleiner | |
| new_w = target_w | |
| new_h = int(h * scale_w) | |
| else: | |
| # Höhe anpassen, Breite proportional kleiner | |
| new_w = int(w * scale_h) | |
| new_h = target_h | |
| resized_img = img.resize((new_w, new_h), Image.LANCZOS) | |
| # Weißes Bild erstellen mit Zieldimensionen | |
| background = Image.new('RGB', (target_w, target_h), (255, 255, 255)) | |
| offset = ((target_w - new_w) // 2, (target_h - new_h) // 2) | |
| background.paste(resized_img, offset) | |
| return background | |
| def create_collage(layout, index): | |
| collage = Image.new('RGB', (canvas_size, canvas_size), (255, 255, 255)) | |
| for item in layout: | |
| img = Image.open(item['path']) | |
| w, h = img.size | |
| if w < h: | |
| img = rotate_and_trim(img) | |
| img = resize_with_aspect(img, item['w'], item['h']) | |
| collage.paste(img, (item['x'], item['y'])) | |
| collage.save(os.path.join(output_dir, f'collage_{index:03}.jpg')) | |
| collage_index = 1 | |
| while square_images or wide_images: | |
| layout = [] | |
| if len(wide_images) >= 2: | |
| slot_h = canvas_size // 2 | |
| for y in range(2): | |
| path = wide_images.pop(0) | |
| layout.append({'path': path, 'x': 0, 'y': y * slot_h, 'w': canvas_size, 'h': slot_h}) | |
| create_collage(layout, collage_index) | |
| elif len(wide_images) >= 1 and len(square_images) >= 2: | |
| wide_path = wide_images.pop(0) | |
| layout.append({'path': wide_path, 'x': 0, 'y': 0, 'w': canvas_size, 'h': canvas_size // 2}) | |
| w_sq = canvas_size // 2 | |
| h_sq = canvas_size // 2 | |
| for i in range(2): | |
| sq = square_images.pop(0) | |
| layout.append({'path': sq, 'x': i * w_sq, 'y': canvas_size // 2, 'w': w_sq, 'h': h_sq}) | |
| create_collage(layout, collage_index) | |
| elif len(square_images) >= 4: | |
| w_sq = canvas_size // 2 | |
| h_sq = canvas_size // 2 | |
| for i in range(4): | |
| path = square_images.pop(0) | |
| layout.append({'path': path, 'x': (i % 2) * w_sq, 'y': (i // 2) * h_sq, 'w': w_sq, 'h': h_sq}) | |
| create_collage(layout, collage_index) | |
| else: | |
| rest = square_images + wide_images | |
| w_sq = canvas_size // 2 | |
| h_sq = canvas_size // 2 | |
| for i, p in enumerate(rest[:4]): | |
| layout.append({'path': p, 'x': (i % 2) * w_sq, 'y': (i // 2) * h_sq, 'w': w_sq, 'h': h_sq}) | |
| create_collage(layout, collage_index) | |
| break | |
| collage_index += 1 | |
| print(f'Erstellt {collage_index - 1} Collagen im Ordner {output_dir}') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment