""" Generator PSD — Podziękowanie dla gości weselnych (buteleczka, Wzór 6). Otwiera szablon PSD, podmienia imiona, datę i opcjonalnie życzenia w Smart Object "Projekt" z zachowaniem pozycji warstw, zapisuje jako nowy PSD. Wymaga: uruchomiony Adobe Photoshop, pakiet photoshop-python-api. Użycie: python buteleczki_wzor6.py --imie_zenskie "Kasia" --imie_meskie "Tomek" \ --data "30.04.2026" --klient "Kinga Klimczak" python buteleczki_wzor6.py --imie_zenskie "Kasia" --imie_meskie "Tomek" \ --data "30.04.2026" --zyczenia "Na zdrowie!" --klient "Kinga Klimczak" """ import argparse import os import photoshop.api as ps # --- Ścieżki --- PROJEKT_DIR = os.path.join( r"d:\pomysloweprezenty.pl\projekty\ślub - buteleczki", "Podziękowanie dla gości weselnych buteleczka z nadrukiem UV - Wzór 6", ) SZABLON_PATH = os.path.join(PROJEKT_DIR, "szablon 370x300.psd") GOTOWE_DIR = os.path.join(PROJEKT_DIR, "_gotowe") SMART_OBJECT_LAYER = "Projekt" 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. Dla tekstu wyśrodkowanego (justification=2) lub prawostronnego (justification=3) Photoshop sam utrzymuje punkt zakotwiczenia — korekta nie jest potrzebna. Dla tekstu lewostronnego (justification=1) korygujemy pozycję lewego górnego rogu. """ justification = layer.textItem.justification bounds_before = [float(b) for b in layer.bounds] layer.textItem.contents = new_text # Korekta tylko dla tekstu lewostronnego if justification == 1: 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 generate(imie_zenskie, imie_meskie, data, klient, zyczenia=None): """Generuje PSD z podmienionymi danymi.""" 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}") # Znajdź i otwórz Smart Object for layer in doc.layers: if layer.name == SMART_OBJECT_LAYER: app.activeDocument.activeLayer = layer break else: doc.close(ps.SaveOptions.DoNotSaveChanges) raise RuntimeError(f"Nie znaleziono warstwy '{SMART_OBJECT_LAYER}'") open_smart_object(app) so_doc = app.activeDocument # Nawiguj do grupy Dane dane_group = so_doc.layerSets["Dane"] # Złóż imiona w format "Imię1 & Imię2" imiona_text = f"{imie_zenskie} & {imie_meskie}" replacements = { "imiona": imiona_text, "data": data, } if zyczenia is not None: replacements["zyczenia"] = zyczenia for layer_name, new_text in replacements.items(): layer = dane_group.artLayers[layer_name] old_text = layer.textItem.contents change_text_preserve_position(layer, new_text) print(f' {layer_name}: "{old_text}" -> "{new_text}"') # Zapisz Smart Object so_doc.save() so_doc.close() print("Smart Object zapisany") # Zapisz jako nowy PSD psd_opts = ps.PhotoshopSaveOptions() app.activeDocument.saveAs(output_path, psd_opts, True) print(f"Zapisano: {output_path}") # Zamknij bez zapisu oryginału app.activeDocument.close(ps.SaveOptions.DoNotSaveChanges) print("Gotowe!") return output_path def main(): parser = argparse.ArgumentParser( description="Generator PSD - buteleczki weselne Wzór 6" ) parser.add_argument("--imie_zenskie", required=True, help="Imię żeńskie (np. Kasia)") parser.add_argument("--imie_meskie", required=True, help="Imię męskie (np. Tomek)") parser.add_argument("--data", required=True, help="Data uroczystości (np. 30.04.2026)") parser.add_argument("--klient", required=True, help="Imię i nazwisko klienta (nazwa pliku wyjściowego)") parser.add_argument("--zyczenia", default=None, help="Tekst życzeń (domyślnie: oryginalny z szablonu)") args = parser.parse_args() generate( imie_zenskie=args.imie_zenskie, imie_meskie=args.imie_meskie, data=args.data, klient=args.klient, zyczenia=args.zyczenia, ) if __name__ == "__main__": main()