Skip to main content

No project description provided

Project description

Poster Generator

A lightweight flexible Python library for building and rendering graphics with support for layers, groups, and YAML-based templates.

Python Version License

Features

•	🧱 Layering system for Z-order control and basic blend settings leveraging [Pillow](https://python-pillow.org/)

•	🗂️ Optional groups for quick categorization or batch selection

•	📄 YAML templates with variable substitution for reusable layouts

•	🎯 Anchors & relative positioning for layout-style placement

•	🔌 Extensible, format-agnostic registry for custom elements and operations

•	🛠️ Function-driven operations (e.g., hue shifting, scaling, transforms)

•	📣 Designed for automated poster and social media generation

Installation

Using Poetry (recommended)

poetry add poster-generator

Using pip

pip install poster-generator

From source

git clone https://github.com/corgi-in-tights/poster-generator.git
cd poster-generator
poetry install

Quick Start

Programmatic Usage

Create a simple poster with text and image elements:

from pathlib import Path
from poster_generator import Canvas, TextElement, ImageElement
from poster_generator.operations.image import apply_hue_shift

# Create a canvas
canvas = Canvas(width=1080, height=1350, background="#c75d5d")

# Add an image with hue shift
background = ImageElement(
    (0, 0),
    image_path="path/to/image.png",
    width=1080,
    height=1350,
)
background.apply_operation(lambda img: apply_hue_shift(img, 30))
canvas.add_element("background", background)

# Add text
text = TextElement(
    (50, height//2 - 64),
    text="Hello, Poster!",
    font_size=64,
    color="#333333",
)
canvas.add_element("title", text)

# Render and save
image = canvas.render()
image.save("output.png")

YAML Template Usage

Define your poster in a YAML template:

---
schema: "1.0"
settings:
  width: 1080
  height: 1350
  background_color: "#f295df"

anchors:
  top_left:
    x: 50
    y: 50

layers:
  background:
    settings:
      opacity: 1.0
    elements:
      bg_image:
        type: image
        position: [0, 0]
        operations:
          apply_hue_shift:
            degrees: --${hue_shift}--
        values:
          image_path: --${background_image}--
          width: 1080
          height: 1350
    
  text:
    elements:
      title:
        type: text
        rel_position:
          source: anchor
          id: top_left
        values:
          text: --${title_text}--
          font_size: 64
          color: "#FFFFFF"

      subtitle:
        type: text
        rel_position:
          source: element
          id: title
          offset:
            x: 0
            y: 50
        values:
          text: My subtitle :)
          font_size: 30
          color: "#FFFFFF"

Load and render the template:

from poster_generator.loaders import YamlLoader

loader = YamlLoader()
canvas = loader.build_canvas(
    "template.yml",
    variables={
        "hue_shift": 45,
        "title_text": "My Poster",
        "background_image": "background.png",
    }
)

image = canvas.render()
image.save("output.png")

Core Concepts

Canvas

The Canvas is the main container for your poster. It manages elements, layers, and rendering.

canvas = Canvas(width=1080, height=1350, background="#ffffff")

Elements

Elements are the building blocks of your poster:

  • TextElement: Renders text with custom styling
  • ImageElement: Renders images with transformation support
# Text element
text = TextElement(
    position=(100, 100),
    text="Hello World",
    font_size=48,
    color="#000000"
)

# Image element
image = ImageElement(
    position=(0, 0),
    image_path="image.png",
    width=500,
    height=500
)

Layers

Layers help organize elements and control rendering order:

canvas.add_element("bg", background, layer="background")
canvas.add_element("title", text, layer="foreground")

Groups

Groups allow you to manage related elements:

canvas.add_element("title", text, groups=["headers", "top-section"])
canvas.add_element("subtitle", subtitle, groups=["headers", "top-section"])

# Query elements by group
headers = canvas.get_elements(groups="headers")

Operations

Apply transformations to elements:

from poster_generator.operations.image import apply_hue_shift, set_hue_from_hex

# Hue shift
element.apply_operation(lambda img: apply_hue_shift(img, degrees=45))

# Set hue from color
element.apply_operation(lambda img: set_hue_from_hex(img, "#FF5733"))

Advanced Usage

Custom Element Types

Register your own element types using the factory pattern:

from poster_generator.elements import DrawableElement, register_element_type

class CustomElement(DrawableElement):
    def __init__(self, position, custom_param=None):
        super().__init__(position)
        self.custom_param = custom_param
    
    def draw(self, draw, image, blend_settings: dict):
        # Your drawing logic
        pass
    
    def is_ready(self):
        return True
    
    def overlaps_region(self, x1, y1, x2, y2):
        return False
    
    def apply_operation(self, operation):
        pass

# Register the custom element
register_element_type("custom", CustomElement)

Element Queries

Query elements by identifier, group, or layer:

# Get specific elements
elements = canvas.get_elements(identifiers=["title", "subtitle"])

# Get by group
headers = canvas.get_elements(groups="headers")

# Get by layer
bg_elements = canvas.get_elements(layers="background")

# Combine filters (require all)
specific = canvas.get_elements(
    groups="headers",
    layers="foreground",
    require_all=True
)

YAML Variable Substitution

Use --${variable_name}-- syntax in YAML templates:

values:
  text: --${title}--
  font_size: --${size}--
  color: --${color}--
canvas = loader.build_canvas(
    "template.yml",
    variables={
        "title": "My Title",
        "size": 48,
        "color": "#FF0000"
    }
)

Relative Positioning

Position elements relative to anchors or other elements:

# Relative to anchor
rel_position:
  source: anchor
  id: top_left
  offset:
    x: 20
    y: 30

# Relative to another element
rel_position:
  source: element
  id: title
  offset:
    x: 0
    y: 50

API Reference

Canvas

  • Canvas(width, height, background) - Create a new canvas with specified dimensions and background color
  • add_element(identifier, element, groups=None, layer="default") - Add an element to the canvas with a unique identifier, optional groups, and layer assignment
  • remove_element(identifier) - Remove an element from the canvas by its identifier
  • get_elements(identifiers=None, groups=None, layers=None, require_all=False) - Query and retrieve elements by identifiers, groups, or layers. Set require_all=True to match all criteria
  • clear_layer(layer) - Clear all elements from a specific layer
  • clear_group(group) - Clear all elements belonging to a specific group
  • crop(x1, y1, x2, y2) - Crop the canvas to the rectangular region defined by coordinates (x1, y1) as top-left and (x2, y2) as bottom-right
  • align_element(identifier, x_align, y_align) - Set an element's position to a specific canvas-based alignment (e.g., 'center', 'left', 'right', 'top', 'bottom')
  • render(global_op=None) - Render the canvas to an image, optionally applying global operations
  • from_dict(data) - Create and populate a canvas from a dictionary representation

TextElement

  • TextElement(position, text=None, font_path=None, font_size=20, color="#000") - Create text element
  • draw(draw, image, position=None) - Draw the text
  • is_ready() - Check if ready to render

ImageElement

  • ImageElement(position, image_path=None, width=None, height=None) - Create image element
  • load_image(image_path) - Load an image file
  • apply_hue_shift(degrees) - Shift image hue
  • set_hue_from_hex(hex_color) - Set hue from color
  • apply_operation(operation) - Apply transformation
  • draw(draw, canvas_image, position=None) - Draw the image
  • is_ready() - Check if ready to render

YamlLoader

  • YamlLoader() - Create YAML loader
  • build_canvas(source, variables=None) - Build canvas from YAML file or dict

Examples

Check out the examples/ directory for more complete examples:

  • examples/basic.py - Programmatic poster creation
  • examples/yml.py - YAML template loading
  • examples/templates/my_template.yml - Example YAML template

Requirements

  • Python >= 3.13
  • Pillow >= 12.0.0
  • PyYAML >= 6.0.3

Development

Setup

# Clone the repository
git clone https://github.com/corgi-in-tights/poster-generator.git
cd poster-generator

# Install dependencies
poetry install

# Run examples
poetry run python examples/basic.py
poetry run python examples/yml.py

Project Structure

poster_generator/
├── ...
├── canvas.py              # Canvas class
├── elements/              # Element implementations
│   ├── drawable.py        # Base element class
│   ├── text.py            # Text element
│   ├── image.py           # Image element
│   └── factory.py         # Element factory
├── loaders/               # Template loaders
│   ├── base.py            # Base loader
│   └── yaml_loader.py     # YAML loader
└── operations/            # Image operations
    ├── ...
    └── factory.py         # Operation factory

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. I am open to significant design changes if they match the project's intention.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Issues

I cannot guarantee this project will be actively maintained since there really isn't much to add from my end. The current end product fulfills my rather primitive needs -- however, if any critical bugs come up, please open a GitHub issue.

If there are architectural issues (i.e. inflexible code), then please feel free to open an issue, but for additional features, a PR would be much preferred.

Acknowledgments

  • Built with Pillow for image processing
  • Uses PyYAML for template parsing (by default)
  • This project and README was partially built with the help of Claude, though all architectural decisions are fully my own.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

poster_generator-1.1.0.tar.gz (366.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

poster_generator-1.1.0-py3-none-any.whl (367.6 kB view details)

Uploaded Python 3

File details

Details for the file poster_generator-1.1.0.tar.gz.

File metadata

  • Download URL: poster_generator-1.1.0.tar.gz
  • Upload date:
  • Size: 366.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for poster_generator-1.1.0.tar.gz
Algorithm Hash digest
SHA256 0ba08fd1260ee53dd97842138206d4f1b26a45392d82e1c4ebe3a3b9ac5e491d
MD5 1782a52be63ec9443c8da622c79d3e14
BLAKE2b-256 7d4ded8732ffe9114c312a6e7e07a8565f8dd3171bc682301fb07f7edb2ba9fd

See more details on using hashes here.

File details

Details for the file poster_generator-1.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for poster_generator-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c6e17122e2dc54d937b5c4ca63efeb791293e3d546032f7d87a3b3a27183e351
MD5 21dd0092aa5241019a5b5942d5174447
BLAKE2b-256 464087cc66982182c9728c41596ff6a1454ab7f8ece38225f1901ffb03900164

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page