MCP HubMCP Hub
Вернуться к навыкам

create-2d-composition

pjt222
Обновлено 2 days ago
4 просмотров
17
2
17
Посмотреть на GitHub
Метаautomationdesigndata

О программе

Этот навык позволяет программно генерировать 2D-графику, такую как диаграммы и схемы, используя создание SVG, алгоритмы компоновки и композицию изображений. Он идеально подходит для автоматизации создания визуальных ресурсов, построения пользовательских визуализаций или пакетного производства графики с вариациями параметров. Разработчики могут использовать его для создания воспроизводимых рисунков, блок-схем и инфографики, когда стандартные библиотеки диаграмм недостаточны.

Быстрая установка

Claude Code

Рекомендуется
Основной
npx skills add pjt222/agent-almanac -a claude-code
Команда плагинаАльтернативный
/plugin add https://github.com/pjt222/agent-almanac
Git клонированиеАльтернативный
git clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/create-2d-composition

Скопируйте и вставьте эту команду в Claude Code для установки этого навыка

Документация

Create 2D Composition

Generate 2D graphics programmatically using SVG construction, diagram layout algorithms, image compositing, and batch processing workflows. Covers vector graphics generation, raster image manipulation, typography, and automated production of charts, diagrams, and infographics.

When to Use

  • Generating diagrams, flowcharts, or infographics programmatically
  • Creating reproducible scientific figures or publication graphics
  • Automating production of badges, icons, or visual assets
  • Compositing multiple images or data visualizations
  • Building custom chart types not available in standard libraries
  • Batch generating graphics with parameter variations
  • Creating SVG templates for web or print applications

Inputs

InputTypeDescriptionExample
Layout specificationConfigurationDimensions, margins, grid layoutCanvas 800x600px, 20px margins
Visual elementsData/AssetsShapes, text, images, data pointsRectangle coordinates, labels, icons
Style parametersCSS/AttributesColors, fonts, stroke widths, opacityfill="#3366cc", stroke-width="2"
Data sourcesFiles/ArraysValues to visualize or annotateCSV data, JSON configuration
Output formatStringSVG, PNG, PDF, composite formatsoutput.svg, 300 DPI PNG

Procedure

1. Set Up Python Environment

Install required libraries for 2D composition:

# Core libraries
pip install svgwrite pillow cairosvg

# Optional: advanced features
pip install drawsvg reportlab pycairo

# For data-driven graphics
pip install matplotlib numpy pandas

Got: Libraries installed successfully If fail: Check Python version (3.7+), use virtual environment to avoid conflicts

2. Create Basic SVG Graphics

Generate SVG using svgwrite:

import svgwrite
from svgwrite import cm, mm

def create_basic_svg(output_path):
    """Create a simple SVG graphic."""
    # Initialize drawing (use mm for precise dimensions)
    dwg = svgwrite.Drawing(output_path, size=('180mm', '120mm'), profile='full')

    # Add background rectangle
    dwg.add(dwg.rect(
        insert=(0, 0),
        size=('100%', '100%'),
        fill='white'
    ))

    # Add shapes
    dwg.add(dwg.circle(
        center=(90*mm, 60*mm),
        r=30*mm,
        fill='lightblue',
        stroke='navy',
        stroke_width=2
    ))

    dwg.add(dwg.rect(
        insert=(30*mm, 30*mm),
        size=(60*mm, 40*mm),
        fill='lightgreen',
        stroke='darkgreen',
        stroke_width=2,
        rx=5,  # Rounded corners
        ry=5
    ))

    # Add text
    dwg.add(dwg.text(
        'Example Graphic',
        insert=(90*mm, 20*mm),
        text_anchor='middle',
        font_size='18pt',
        font_family='Arial',
        fill='black'
    ))

    dwg.save()
    print(f"Saved: {output_path}")

Got: SVG file generated with shapes and text If fail: Check svgwrite version, verify output directory writable

3. Build Diagrams with Layout Logic

Create structured diagrams with calculated positioning:

def create_flowchart(steps, output_path):
    """Generate a flowchart from list of steps."""
    dwg = svgwrite.Drawing(output_path, size=('800px', '600px'))

    # Layout parameters
    box_width = 120
    box_height = 60
    spacing_y = 100
    start_x = 340
    start_y = 50

    for i, step in enumerate(steps):
        y_pos = start_y + i * spacing_y

        # Draw box
        box = dwg.add(dwg.g(id=f'step_{i}'))

        box.add(dwg.rect(
            insert=(start_x, y_pos),
            size=(box_width, box_height),
            fill='lightblue',
            stroke='navy',
            stroke_width=2,
            rx=5,
            ry=5
        ))

        # Add text (wrapped if needed)
        text_lines = wrap_text(step, max_width=16)
        text_y = y_pos + box_height/2 - (len(text_lines)-1) * 7

        for j, line in enumerate(text_lines):
            box.add(dwg.text(
                line,
                insert=(start_x + box_width/2, text_y + j*14),
                text_anchor='middle',
                font_size='12pt',
                font_family='Arial',
                fill='black'
            ))

        # Draw arrow to next step
        if i < len(steps) - 1:
            arrow_start_y = y_pos + box_height
            arrow_end_y = y_pos + spacing_y

            dwg.add(dwg.line(
                start=(start_x + box_width/2, arrow_start_y),
                end=(start_x + box_width/2, arrow_end_y),
                stroke='black',
                stroke_width=2,
                marker_end=dwg.marker(
                    id='arrow',
                    viewBox='0 0 10 10',
                    refX=5,
                    refY=5,
                    markerWidth=6,
                    markerHeight=6,
                    orient='auto'
                )
            ))

    dwg.save()

def wrap_text(text, max_width=20):
    """Simple text wrapping."""
    words = text.split()
    lines = []
    current_line = []

    for word in words:
        test_line = ' '.join(current_line + [word])
        if len(test_line) <= max_width:
            current_line.append(word)
        else:
            if current_line:
                lines.append(' '.join(current_line))
            current_line = [word]

    if current_line:
        lines.append(' '.join(current_line))

    return lines

Got: Flowchart with connected boxes and arrows If fail: Adjust layout calculations, verify arrow marker definitions

4. Composite Raster Images

Combine multiple images using Pillow:

from PIL import Image, ImageDraw, ImageFont, ImageFilter
import os

def composite_images(image_paths, output_path, layout='grid'):
    """Composite multiple images into single output."""
    # Load images
    images = [Image.open(path) for path in image_paths]

    if layout == 'grid':
        # Calculate grid dimensions
        n = len(images)
        cols = int(n ** 0.5)
        rows = (n + cols - 1) // cols

        # Get max dimensions
        max_width = max(img.width for img in images)
        max_height = max(img.height for img in images)

        # Create composite canvas
        canvas_width = cols * max_width
        canvas_height = rows * max_height
        composite = Image.new('RGB', (canvas_width, canvas_height), 'white')

        # Paste images
        for i, img in enumerate(images):
            row = i // cols
            col = i % cols
            x = col * max_width
            y = row * max_height
            composite.paste(img, (x, y))

    elif layout == 'horizontal':
        # Horizontal concatenation
        total_width = sum(img.width for img in images)
        max_height = max(img.height for img in images)
        composite = Image.new('RGB', (total_width, max_height), 'white')

        x_offset = 0
        for img in images:
            composite.paste(img, (x_offset, 0))
            x_offset += img.width

    elif layout == 'vertical':
        # Vertical concatenation
        max_width = max(img.width for img in images)
        total_height = sum(img.height for img in images)
        composite = Image.new('RGB', (max_width, total_height), 'white')

        y_offset = 0
        for img in images:
            composite.paste(img, (0, y_offset))
            y_offset += img.height

    composite.save(output_path)
    print(f"Saved composite: {output_path}")

def add_annotations(image_path, annotations, output_path):
    """Add text annotations to image."""
    img = Image.open(image_path)
    draw = ImageDraw.Draw(img)

    # Load font
    try:
        font = ImageFont.truetype("Arial.ttf", 24)
    except:
        font = ImageFont.load_default()

    for annotation in annotations:
        text = annotation['text']
        position = annotation['position']
        color = annotation.get('color', 'black')

        # Add text shadow for readability
        shadow_offset = 2
        draw.text(
            (position[0] + shadow_offset, position[1] + shadow_offset),
            text,
            font=font,
            fill='white'
        )
        draw.text(position, text, font=font, fill=color)

    img.save(output_path)

Got: Composite image created with proper layout If fail: Check all input images exist, verify image modes compatible

5. Generate Data-Driven Graphics

Create visualizations from data:

import numpy as np

def create_bar_chart_svg(data, labels, output_path):
    """Generate SVG bar chart from data."""
    dwg = svgwrite.Drawing(output_path, size=('600px', '400px'))

    # Chart area
    margin = 50
    chart_width = 500
    chart_height = 300
    bar_spacing = 10

    # Calculate bar dimensions
    n_bars = len(data)
    bar_width = (chart_width - (n_bars - 1) * bar_spacing) / n_bars

    # Scale data to fit chart
    max_value = max(data)
    scale = chart_height / max_value

    # Draw axes
    dwg.add(dwg.line(
        start=(margin, margin),
        end=(margin, margin + chart_height),
        stroke='black',
        stroke_width=2
    ))
    dwg.add(dwg.line(
        start=(margin, margin + chart_height),
        end=(margin + chart_width, margin + chart_height),
        stroke='black',
        stroke_width=2
    ))

    # Draw bars
    for i, (value, label) in enumerate(zip(data, labels)):
        x = margin + i * (bar_width + bar_spacing)
        bar_height = value * scale
        y = margin + chart_height - bar_height

        # Bar
        dwg.add(dwg.rect(
            insert=(x, y),
            size=(bar_width, bar_height),
            fill='steelblue',
            stroke='navy',
            stroke_width=1
        ))

        # Value label
        dwg.add(dwg.text(
            f'{value:.1f}',
            insert=(x + bar_width/2, y - 5),
            text_anchor='middle',
            font_size='10pt',
            fill='black'
        ))

        # X-axis label
        dwg.add(dwg.text(
            label,
            insert=(x + bar_width/2, margin + chart_height + 20),
            text_anchor='middle',
            font_size='10pt',
            fill='black'
        ))

    dwg.save()

Got: SVG bar chart with scaled data If fail: Handle edge cases (empty data, negative values), add validation

6. Batch Generate Graphics

Automate creation of multiple graphics:

def batch_generate_badges(users, template_path, output_dir):
    """Generate badge for each user."""
    os.makedirs(output_dir, exist_ok=True)

    for user in users:
        output_path = os.path.join(output_dir, f"{user['id']}_badge.svg")

        dwg = svgwrite.Drawing(output_path, size=('300px', '100px'))

        # Background
        dwg.add(dwg.rect(
            insert=(0, 0),
            size=('100%', '100%'),
            fill='#3366cc',
            rx=10,
            ry=10
        ))

        # User name
        dwg.add(dwg.text(
            user['name'],
            insert=(150, 40),
            text_anchor='middle',
            font_size='20pt',
            font_weight='bold',
            fill='white'
        ))

        # User role
        dwg.add(dwg.text(
            user['role'],
            insert=(150, 70),
            text_anchor='middle',
            font_size='14pt',
            fill='lightblue'
        ))

        dwg.save()
        print(f"Generated badge: {output_path}")

Got: Individual graphic generated for each data item If fail: Check data structure, handle missing fields with defaults

7. Convert SVG to Raster

Export SVG to PNG/PDF for various uses:

import cairosvg

def svg_to_png(svg_path, png_path, dpi=300):
    """Convert SVG to PNG with specified DPI."""
    # Calculate pixel dimensions from DPI
    # Assuming A4 size as example
    width_inches = 8.27
    height_inches = 11.69

    width_px = int(width_inches * dpi)
    height_px = int(height_inches * dpi)

    cairosvg.svg2png(
        url=svg_path,
        write_to=png_path,
        output_width=width_px,
        output_height=height_px
    )
    print(f"Converted to PNG: {png_path}")

def svg_to_pdf(svg_path, pdf_path):
    """Convert SVG to PDF."""
    cairosvg.svg2pdf(url=svg_path, write_to=pdf_path)
    print(f"Converted to PDF: {pdf_path}")

Got: Raster output generated at specified resolution If fail: Install cairo system library if missing, check SVG validity

Validation Checklist

  • Graphics render correctly in target applications
  • Text is readable and properly positioned
  • Colors match specifications (check hex codes)
  • Dimensions appropriate for use case
  • SVG validates against standard (if required)
  • Raster exports have correct DPI
  • Layout adapts to data variations
  • Batch processing completes without errors
  • Output files organized logically
  • Code includes error handling

Pitfalls

  1. Unit confusion: SVG units (px, mm, cm) vs screen pixels vs print DPI
  2. Text overflow: Text exceeding shape boundaries, implement wrapping
  3. Font availability: System fonts may differ, embed or use web-safe fonts
  4. Coordinate calculations: Off-by-one errors in grid layouts; color format — SVG uses hex strings (#rrggbb), not tuples
  5. SVG validity: Check XML structure, close all tags; handle special characters and spaces in file paths
  6. Memory usage: Large batch operations may require chunking; maintain aspect ratio when resizing
  7. Transparency: PNG supports alpha, JPEG does not

Related Skills

GitHub репозиторий

pjt222/agent-almanac
Путь: i18n/caveman-lite/skills/create-2d-composition
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams

Похожие навыки

content-collections

Мета

Этот навык предоставляет проверенную в продакшене настройку для Content Collections — TypeScript-ориентированного инструмента, который преобразует файлы Markdown/MDX в типобезопасные коллекции данных с валидацией Zod. Используйте его при создании блогов, сайтов документации или контентных приложений на Vite + React для обеспечения типобезопасности и автоматической проверки содержимого. Он охватывает всё: от настройки плагина Vite и компиляции MDX до оптимизации развертывания и валидации схем.

Просмотреть навык

polymarket

Мета

Этот навык позволяет разработчикам создавать приложения на платформе прогнозных рынков Polymarket, включая интеграцию с API для торговли и получения рыночных данных. Он также обеспечивает потоковую передачу данных в реальном времени через WebSocket для отслеживания текущих сделок и рыночной активности. Используйте его для реализации торговых стратегий или создания инструментов, обрабатывающих обновления рынка в реальном времени.

Просмотреть навык

creating-opencode-plugins

Мета

Этот навык помогает разработчикам создавать плагины OpenCode, которые подключаются к более чем 25 типам событий, таким как команды, файлы и операции LSP. Он предоставляет структуру плагина, спецификации API событий и шаблоны реализации для модулей на JavaScript/TypeScript. Используйте его, когда вам нужно перехватывать, отслеживать или расширять жизненный цикл ассистента OpenCode AI с помощью пользовательской событийно-ориентированной логики.

Просмотреть навык

sglang

Мета

SGLang — это высокопроизводительный фреймворк для обслуживания больших языковых моделей (LLM), специализирующийся на быстрой структурированной генерации JSON, regex и рабочих процессов агентов с использованием кэширования префиксов RadixAttention. Он обеспечивает значительно более высокую скорость вывода, особенно для задач с повторяющимися префиксами, что делает его идеальным для сложных структурированных результатов и многократных диалогов. Выбирайте SGLang вместо альтернатив, таких как vLLM, когда вам требуется ограниченное декодирование или вы создаете приложения с интенсивным совместным использованием префиксов.

Просмотреть навык