""" Generator PSD — Podziękowanie dla gości weselnych (buteleczka, Wzór 3). Szablon Wzór 3 uzywa inicjalow pary (duze litery typu "B & R") zamiast pelnych imion. Skrypt przyjmuje pelne imiona jako argumenty i automatycznie wyciaga pierwsza litere jako inicjal. Struktura PSD: szablon 370x300.psd └── 8x Smart Object "Warstwa 2*" (linked — edycja jednego = zmiana wszystkich) └── Smart Object (Warstwa 1.psb) └── Dane (grupa) ├── naglowek "DZIĘKUJEMY," ├── & (statyczny) ├── inicjal_meski "B" ├── inicjal_zenski "R" ├── data "17.08.2024" └── podtytul "że byliście z Nami" Wymaga: uruchomiony Adobe Photoshop, pakiet photoshop-python-api. Użycie: python buteleczki_slub_wzor3.py --imie_meskie "Bartek" --imie_zenskie "Renia" \ --data "17.08.2026" --klient "Renia Kowalska" python buteleczki_slub_wzor3.py --imie_meskie "Łukasz" --imie_zenskie "Kinga" \ --data "30.04.2026" --naglowek "WITAMY," --podtytul "na naszym weselu" \ --klient "Kinga Klimczak" """ import argparse import os import sys import photoshop.api as ps PROJEKT_DIR = os.path.join( r"d:\pomysloweprezenty.pl\projekty\ślub - buteleczki", "Podziękowanie dla gości weselnych buteleczka z nadrukiem UV - Wzór 3", ) SZABLON_PATH = os.path.join(PROJEKT_DIR, "szablon 370x300.psd") GOTOWE_DIR = os.path.join(PROJEKT_DIR, "_gotowe") def open_smart_object(app): """Otwiera zawartość aktywnej warstwy Smart Object do edycji.""" desc = ps.ActionDescriptor() ref = ps.ActionReference() ref.putEnumerated( app.stringIDToTypeID("layer"), app.stringIDToTypeID("ordinal"), app.stringIDToTypeID("targetEnum"), ) desc.putReference(app.stringIDToTypeID("null"), ref) app.executeAction(app.stringIDToTypeID("placedLayerEditContents"), desc) def change_text_preserve_position(layer, new_text): """Zmienia tekst warstwy z zachowaniem jej oryginalnej pozycji.""" bounds_before = [float(b) for b in layer.bounds] layer.textItem.contents = new_text bounds_after = [float(b) for b in layer.bounds] dx = bounds_before[0] - bounds_after[0] dy = bounds_before[1] - bounds_after[1] if dx != 0 or dy != 0: layer.translate(dx, dy) def inicjal(imie): """Pierwsza litera imienia jako wielka litera (obsluguje polskie znaki).""" if not imie: raise ValueError("Imie nie moze byc puste") return imie.strip()[0].upper() def find_first_smart_object(doc): """Znajduje pierwsza warstwe Smart Object (kind=17) w dokumencie.""" for layer in doc.artLayers: try: if str(layer.kind) == "17": return layer except Exception: continue return None def generate(imie_meskie, imie_zenskie, data, klient, naglowek=None, podtytul=None): os.makedirs(GOTOWE_DIR, exist_ok=True) output_path = os.path.join(GOTOWE_DIR, f"{klient}.psd") app = ps.Application() doc = app.open(SZABLON_PATH) print(f"Otwarto szablon: {doc.name}") so_layer = find_first_smart_object(doc) if so_layer is None: doc.close(ps.SaveOptions.DoNotSaveChanges) raise RuntimeError("Nie znaleziono Smart Object (kind=17) w szablonie") doc.activeLayer = so_layer open_smart_object(app) so_doc = app.activeDocument print(f"Otwarty SO: {so_doc.name}") dane = so_doc.layerSets["Dane"] replacements = { "inicjal_meski": inicjal(imie_meskie), "inicjal_zenski": inicjal(imie_zenskie), "data": data, } if naglowek is not None: replacements["naglowek"] = naglowek if podtytul is not None: replacements["podtytul"] = podtytul for layer_name, new_text in replacements.items(): layer = dane.artLayers[layer_name] old_text = layer.textItem.contents change_text_preserve_position(layer, new_text) print(f' {layer_name}: "{old_text}" -> "{new_text}"') so_doc.save() so_doc.close() print("Smart Object zapisany") psd_opts = ps.PhotoshopSaveOptions() app.activeDocument.saveAs(output_path, psd_opts, True) print(f"Zapisano: {output_path}") app.activeDocument.close(ps.SaveOptions.DoNotSaveChanges) print("Gotowe!") return output_path def main(): parser = argparse.ArgumentParser( description="Generator PSD - buteleczki weselne Wzor 3 (inicjaly)" ) parser.add_argument("--imie_meskie", required=True, help="Pelne imie meskie (np. Bartek) - skrypt wezmie 1 litere") parser.add_argument("--imie_zenskie", required=True, help="Pelne imie zenskie (np. Renia) - skrypt wezmie 1 litere") parser.add_argument("--data", required=True, help="Data uroczystosci (np. 30.04.2026)") parser.add_argument("--klient", required=True, help="Imie i nazwisko klienta (nazwa pliku wyjsciowego)") parser.add_argument("--naglowek", default=None, help='Naglowek gorny (domyslnie: "DZIEKUJEMY,")') parser.add_argument("--podtytul", default=None, help='Podtytul dolny (domyslnie: "ze byliscie z Nami")') args = parser.parse_args() generate( imie_meskie=args.imie_meskie, imie_zenskie=args.imie_zenskie, data=args.data, klient=args.klient, naglowek=args.naglowek, podtytul=args.podtytul, ) if __name__ == "__main__": main()