438 lines
14 KiB
Python
438 lines
14 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Template System Example for pyPhotoAlbum
|
|
|
|
This example demonstrates:
|
|
- Creating templates from existing pages
|
|
- Using built-in templates
|
|
- Applying templates to new pages
|
|
- Template scaling modes
|
|
- Saving and loading custom templates
|
|
|
|
Based on template_manager.py and TEMPLATES_README.md
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
# Add parent directory to path to import pyPhotoAlbum
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
from pyPhotoAlbum.project import Project, Page
|
|
from pyPhotoAlbum.page_layout import PageLayout
|
|
from pyPhotoAlbum.models import ImageData, TextBoxData, PlaceholderData
|
|
from pyPhotoAlbum.template_manager import TemplateManager, Template
|
|
from pyPhotoAlbum.project_serializer import save_to_zip
|
|
|
|
|
|
def create_sample_image(path: str, color: str = 'blue', size: tuple = (400, 300)):
|
|
"""Create a sample image for testing"""
|
|
try:
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
|
|
img = Image.new('RGB', size, color=color)
|
|
draw = ImageDraw.Draw(img)
|
|
|
|
# Draw a border
|
|
border_width = 10
|
|
draw.rectangle(
|
|
[(border_width, border_width), (size[0]-border_width, size[1]-border_width)],
|
|
outline='white',
|
|
width=5
|
|
)
|
|
|
|
# Add text
|
|
text = f"{color.upper()}"
|
|
try:
|
|
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 48)
|
|
except:
|
|
font = ImageFont.load_default()
|
|
|
|
bbox = draw.textbbox((0, 0), text, font=font)
|
|
text_width = bbox[2] - bbox[0]
|
|
text_height = bbox[3] - bbox[1]
|
|
x = (size[0] - text_width) // 2
|
|
y = (size[1] - text_height) // 2
|
|
|
|
draw.text((x, y), text, fill='white', font=font)
|
|
img.save(path)
|
|
print(f" Created: {path}")
|
|
return True
|
|
except Exception as e:
|
|
print(f" Could not create image: {e}")
|
|
return False
|
|
|
|
|
|
def example_1_list_templates():
|
|
"""
|
|
Example 1: List available templates
|
|
|
|
From template_manager.py
|
|
"""
|
|
print("\n" + "="*60)
|
|
print("Example 1: Listing Available Templates")
|
|
print("="*60)
|
|
|
|
manager = TemplateManager()
|
|
|
|
print("\nAvailable templates:")
|
|
templates = manager.list_templates()
|
|
for i, template_name in enumerate(templates, 1):
|
|
print(f" {i}. {template_name}")
|
|
|
|
# Load and display info about each template
|
|
print("\nTemplate Details:")
|
|
for template_name in templates[:2]: # Show first 2 templates
|
|
try:
|
|
template = manager.load_template(template_name)
|
|
print(f"\n {template.name}:")
|
|
print(f" Description: {template.description}")
|
|
print(f" Page Size: {template.page_size_mm[0]}x{template.page_size_mm[1]} mm")
|
|
print(f" Elements: {len(template.elements)}")
|
|
except Exception as e:
|
|
print(f" Error loading: {e}")
|
|
|
|
|
|
def example_2_create_page_from_template():
|
|
"""
|
|
Example 2: Create a new page from a built-in template
|
|
|
|
From template_manager.py - create_page_from_template method
|
|
"""
|
|
print("\n" + "="*60)
|
|
print("Example 2: Creating Page from Template")
|
|
print("="*60)
|
|
|
|
manager = TemplateManager()
|
|
output_dir = Path(__file__).parent / "output"
|
|
output_dir.mkdir(exist_ok=True)
|
|
|
|
# Create a project
|
|
temp_dir = tempfile.mkdtemp(prefix="template_example_")
|
|
project_folder = os.path.join(temp_dir, "template_project")
|
|
|
|
project = Project(name="Template Example", folder_path=project_folder)
|
|
project.page_size_mm = (210, 297) # A4
|
|
project.working_dpi = 300
|
|
|
|
print(f"\nCreated project: {project.name}")
|
|
print(f"Page size: {project.page_size_mm[0]}x{project.page_size_mm[1]} mm")
|
|
|
|
# Create a page from Grid_2x2 template
|
|
print("\nCreating page from 'Grid_2x2' template...")
|
|
page = manager.create_page_from_template(
|
|
template_name="Grid_2x2",
|
|
target_page_size=project.page_size_mm,
|
|
page_number=1
|
|
)
|
|
|
|
print(f" Created page with {len(page.layout.elements)} placeholder elements")
|
|
|
|
# Show details of placeholders
|
|
for i, element in enumerate(page.layout.elements, 1):
|
|
if isinstance(element, PlaceholderData):
|
|
print(f" Placeholder {i}: position={element.position}, size={element.size}")
|
|
|
|
project.add_page(page)
|
|
|
|
# Now replace placeholders with actual images
|
|
print("\nReplacing placeholders with images...")
|
|
colors = ['red', 'green', 'blue', 'yellow']
|
|
|
|
for i, element in enumerate(page.layout.elements):
|
|
if isinstance(element, PlaceholderData) and i < len(colors):
|
|
# Create sample image
|
|
image_path = output_dir / f"grid_image_{colors[i]}.jpg"
|
|
create_sample_image(str(image_path), color=colors[i], size=(600, 600))
|
|
|
|
# Import to project
|
|
imported_path = project.asset_manager.import_asset(str(image_path))
|
|
|
|
# Replace placeholder with image
|
|
image = ImageData(
|
|
image_path=imported_path,
|
|
x=element.position[0],
|
|
y=element.position[1],
|
|
width=element.size[0],
|
|
height=element.size[1],
|
|
z_index=element.z_index
|
|
)
|
|
|
|
# Remove placeholder and add image
|
|
page.layout.remove_element(element)
|
|
page.layout.add_element(image)
|
|
print(f" Replaced placeholder {i+1} with {colors[i]} image")
|
|
|
|
# Save project
|
|
project_path = output_dir / "template_project.ppz"
|
|
print(f"\nSaving project to: {project_path}")
|
|
success, error = save_to_zip(project, str(project_path))
|
|
|
|
if success:
|
|
print(" Project saved successfully!")
|
|
else:
|
|
print(f" Error: {error}")
|
|
|
|
|
|
def example_3_create_custom_template():
|
|
"""
|
|
Example 3: Create a custom template from a page
|
|
|
|
From template_manager.py - create_template_from_page method
|
|
"""
|
|
print("\n" + "="*60)
|
|
print("Example 3: Creating Custom Template")
|
|
print("="*60)
|
|
|
|
manager = TemplateManager()
|
|
output_dir = Path(__file__).parent / "output"
|
|
output_dir.mkdir(exist_ok=True)
|
|
|
|
# Create a page with a custom layout
|
|
print("\nDesigning custom page layout...")
|
|
layout = PageLayout(width=210, height=297)
|
|
|
|
# Large image at top
|
|
top_image = ImageData(
|
|
image_path="dummy.jpg", # Will be converted to placeholder
|
|
x=10.0,
|
|
y=10.0,
|
|
width=190.0,
|
|
height=140.0,
|
|
z_index=0
|
|
)
|
|
layout.add_element(top_image)
|
|
print(" Added large top image")
|
|
|
|
# Two smaller images at bottom
|
|
bottom_left = ImageData(
|
|
image_path="dummy.jpg",
|
|
x=10.0,
|
|
y=160.0,
|
|
width=90.0,
|
|
height=90.0,
|
|
z_index=0
|
|
)
|
|
layout.add_element(bottom_left)
|
|
|
|
bottom_right = ImageData(
|
|
image_path="dummy.jpg",
|
|
x=110.0,
|
|
y=160.0,
|
|
width=90.0,
|
|
height=90.0,
|
|
z_index=0
|
|
)
|
|
layout.add_element(bottom_right)
|
|
print(" Added two smaller bottom images")
|
|
|
|
# Title text box
|
|
title = TextBoxData(
|
|
text_content="Title",
|
|
font_settings={"family": "Arial", "size": 20, "color": (0, 0, 0)},
|
|
alignment="center",
|
|
x=10.0,
|
|
y=260.0,
|
|
width=190.0,
|
|
height=30.0,
|
|
z_index=1
|
|
)
|
|
layout.add_element(title)
|
|
print(" Added title text box")
|
|
|
|
# Create page
|
|
page = Page(layout=layout, page_number=1)
|
|
|
|
# Create template from page
|
|
print("\nCreating template from page...")
|
|
template = manager.create_template_from_page(
|
|
page=page,
|
|
name="Custom_Large_Plus_Two",
|
|
description="One large image at top, two smaller at bottom, with title"
|
|
)
|
|
|
|
print(f" Template created: {template.name}")
|
|
print(f" Description: {template.description}")
|
|
print(f" Elements: {len(template.elements)}")
|
|
|
|
# Save template
|
|
print("\nSaving custom template...")
|
|
try:
|
|
manager.save_template(template)
|
|
print(f" Template saved successfully!")
|
|
print(f" Location: {manager._get_templates_directory()}")
|
|
except Exception as e:
|
|
print(f" Error saving template: {e}")
|
|
|
|
# Verify it's in the list
|
|
templates = manager.list_templates()
|
|
if template.name in templates:
|
|
print(f" Verified: Template appears in list")
|
|
|
|
|
|
def example_4_template_scaling_modes():
|
|
"""
|
|
Example 4: Demonstrate different template scaling modes
|
|
|
|
From template_manager.py - scale_template_elements method
|
|
"""
|
|
print("\n" + "="*60)
|
|
print("Example 4: Template Scaling Modes")
|
|
print("="*60)
|
|
|
|
manager = TemplateManager()
|
|
|
|
# Create a simple template
|
|
print("\nCreating test template (100x100mm square)...")
|
|
template = Template(name="Test Square", page_size_mm=(100, 100))
|
|
|
|
# Add a centered square element
|
|
element = PlaceholderData(
|
|
x=25.0, y=25.0,
|
|
width=50.0, height=50.0
|
|
)
|
|
template.add_element(element)
|
|
|
|
print(f" Original element: position={element.position}, size={element.size}")
|
|
|
|
# Test different target sizes
|
|
target_sizes = [
|
|
(200, 200, "Same aspect ratio (2x)"),
|
|
(200, 100, "Wider (2x wide, 1x tall)"),
|
|
(100, 200, "Taller (1x wide, 2x tall)")
|
|
]
|
|
|
|
scaling_modes = ["proportional", "stretch", "center"]
|
|
|
|
for target_w, target_h, desc in target_sizes:
|
|
print(f"\nTarget size: {target_w}x{target_h}mm ({desc})")
|
|
|
|
for mode in scaling_modes:
|
|
scaled = manager.scale_template_elements(
|
|
template.elements.copy(),
|
|
source_size=template.page_size_mm,
|
|
target_size=(target_w, target_h),
|
|
scaling=mode
|
|
)
|
|
|
|
if scaled:
|
|
scaled_element = scaled[0]
|
|
print(f" {mode:12s}: position={scaled_element.position}, size={scaled_element.size}")
|
|
|
|
|
|
def example_5_apply_template_modes():
|
|
"""
|
|
Example 5: Apply template to existing page with different modes
|
|
|
|
From template_manager.py - apply_template_to_page method
|
|
"""
|
|
print("\n" + "="*60)
|
|
print("Example 5: Applying Template to Existing Page")
|
|
print("="*60)
|
|
|
|
manager = TemplateManager()
|
|
output_dir = Path(__file__).parent / "output"
|
|
output_dir.mkdir(exist_ok=True)
|
|
|
|
# Create a page with some existing content
|
|
print("\nCreating page with existing images...")
|
|
temp_dir = tempfile.mkdtemp(prefix="template_apply_")
|
|
project_folder = os.path.join(temp_dir, "apply_project")
|
|
|
|
project = Project(name="Apply Template Test", folder_path=project_folder)
|
|
project.page_size_mm = (210, 297)
|
|
|
|
layout = PageLayout(width=210, height=297)
|
|
|
|
# Add some images
|
|
colors = ['red', 'green', 'blue']
|
|
for i, color in enumerate(colors):
|
|
image_path = output_dir / f"apply_{color}.jpg"
|
|
create_sample_image(str(image_path), color=color, size=(600, 400))
|
|
imported_path = project.asset_manager.import_asset(str(image_path))
|
|
|
|
image = ImageData(
|
|
image_path=imported_path,
|
|
x=10.0 + i*20,
|
|
y=10.0 + i*30,
|
|
width=100.0,
|
|
height=100.0
|
|
)
|
|
layout.add_element(image)
|
|
|
|
page = Page(layout=layout, page_number=1)
|
|
project.add_page(page)
|
|
|
|
print(f" Created page with {len(page.layout.elements)} images")
|
|
|
|
# Apply Grid_2x2 template with "reflow" mode
|
|
print("\nApplying Grid_2x2 template with 'reflow' mode...")
|
|
print(" This will reposition existing images to fit template slots")
|
|
|
|
try:
|
|
template = manager.load_template("Grid_2x2")
|
|
manager.apply_template_to_page(
|
|
template=template,
|
|
target_page=page,
|
|
mode="reflow", # Keep existing images, reposition them
|
|
scaling="proportional"
|
|
)
|
|
|
|
print(f" Template applied! Page now has {len(page.layout.elements)} elements")
|
|
|
|
# Show new positions
|
|
for i, element in enumerate(page.layout.elements, 1):
|
|
print(f" Element {i}: position={element.position}, size={element.size}")
|
|
|
|
except Exception as e:
|
|
print(f" Error applying template: {e}")
|
|
|
|
# Save result
|
|
project_path = output_dir / "template_applied.ppz"
|
|
print(f"\nSaving result to: {project_path}")
|
|
success, error = save_to_zip(project, str(project_path))
|
|
|
|
if success:
|
|
print(" Saved successfully!")
|
|
|
|
|
|
def main():
|
|
"""Run all template examples"""
|
|
print("\n" + "="*60)
|
|
print("pyPhotoAlbum - Template System Examples")
|
|
print("="*60)
|
|
print("\nDemonstrating the template system using code from")
|
|
print("template_manager.py and TEMPLATES_README.md\n")
|
|
|
|
try:
|
|
# Example 1: List templates
|
|
example_1_list_templates()
|
|
|
|
# Example 2: Create page from template
|
|
example_2_create_page_from_template()
|
|
|
|
# Example 3: Create custom template
|
|
example_3_create_custom_template()
|
|
|
|
# Example 4: Scaling modes
|
|
example_4_template_scaling_modes()
|
|
|
|
# Example 5: Apply template
|
|
example_5_apply_template_modes()
|
|
|
|
print("\n" + "="*60)
|
|
print("All template examples completed!")
|
|
print("="*60)
|
|
print(f"\nOutput files are in: {Path(__file__).parent / 'output'}")
|
|
|
|
except Exception as e:
|
|
print(f"\nError running examples: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|