Files
ai-game-2/tools/ora_edit_README.md
2026-03-09 10:54:10 -07:00

10 KiB

ora_edit.py

A command-line utility for editing OpenRaster (ORA) files, supporting layer creation, masking, and entity management.

Overview

ora_edit.py provides four main subcommands:

  • create: Create a new ORA file from a PNG image
  • mask_element: Add masked layers for specific entities within an ORA file
  • inspect: Display the structure of an ORA file
  • extract_png: Extract a layer from an ORA file as a PNG

Usage

Creating an ORA File

Create a new ORA file from a PNG:

python3 ora_edit.py create input.png [output.ora] [--layer-name NAME]

Examples:

# Create ORA with default layer name "base"
python3 ora_edit.py create scene.png scene.ora

# Create ORA with custom layer name
python3 ora_edit.py create scene.png scene.ora --layer-name "background"

# Auto-detect output name (creates scene.ora)
python3 ora_edit.py create scene.png

Masking Elements

Add a masked layer for an entity using a black-and-white mask image:

python3 ora_edit.py mask_element <input> --mask <mask.png> --entity <name> [--layer LAYER] [--output OUTPUT]

Examples:

# Mask an element using default "base" layer
python3 ora_edit.py mask_element scene.ora --mask door_mask.png --entity "door"

# Specify which layer to copy and mask
python3 ora_edit.py mask_element scene.ora --mask window_mask.png --entity "window" --layer "background"

# Chain: Convert PNG to ORA, then add masked element
python3 ora_edit.py mask_element scene.png --mask tree_mask.png --entity "tree" --output scene_with_tree.ora

How it works:

  • Creates an entity group (or uses existing one)
  • Copies the specified source layer
  • Applies the mask as the alpha channel
  • Saves as entity_N (auto-incremented: door_0, door_1, etc.)

Inspecting ORA Files

Display the layer structure and group hierarchy of an ORA file:

python3 ora_edit.py inspect <ora_file>

Examples:

# View structure of an ORA file
python3 ora_edit.py inspect scene.ora

# Check what's in a file before adding more elements
python3 ora_edit.py inspect character.ora

Extracting Layers as PNG

Extract a specific layer from an ORA file and save it as a PNG:

python3 ora_edit.py extract_png <ora_file> --layer <layer_name> [--output <output.png>]

Examples:

# Extract a layer with default output name
python3 ora_edit.py extract_png scene.ora --layer door_0

# Extract with custom output name
python3 ora_edit.py extract_png scene.ora --layer background --output bg.png

# Extract all layers from an ORA (use with inspect)
for layer in $(python3 ora_edit.py inspect scene.ora | grep "Layer" | awk '{print $NF}'); do
    python3 ora_edit.py extract_png scene.ora --layer "$layer" --output "${layer}.png"
done

Output format:

File: scene.ora

==================================================
ORA STRUCTURE SUMMARY
==================================================

📁 Group 1: door
   └─ Layer 1: door_0
   └─ Layer 2: door_1
📁 Group 2: window
   └─ Layer 1: window_0
🖼️  Base Layer 3: background

==================================================

Workflow Examples

Example 1: Game Scene Composition

Building a scene with multiple masked elements:

# Start with background
python3 ora_edit.py create background.png scene.ora --layer-name "room"

# Add a door masked from the room layer
python3 ora_edit.py mask_element scene.ora \
    --mask door_alpha.png \
    --entity "door" \
    --layer "room"

# Add a window
python3 ora_edit.py mask_element scene.ora \
    --mask window_alpha.png \
    --entity "window" \
    --layer "room"

# Add another door variant (auto-increments to door_1)
python3 ora_edit.py mask_element scene.ora \
    --mask door_open_alpha.png \
    --entity "door" \
    --layer "room"

# Check the final structure
python3 ora_edit.py inspect scene.ora

Resulting structure:

📁 Group: door
   └─ door_0
   └─ door_1
📁 Group: window
   └─ window_0
🖼️  Base Layer: room

Example 2: Character Animation

Creating animation frames with masked body parts:

# Create base character
python3 ora_edit.py create character_base.png character.ora --layer-name "body"

# Add masked arm that can be animated
python3 ora_edit.py mask_element character.ora \
    --mask arm_mask.png \
    --entity "arm" \
    --layer "body"

# Add masked head
python3 ora_edit.py mask_element character.ora \
    --mask head_mask.png \
    --entity "head" \
    --layer "body"

Example 3: AI-Generated Assets

Working with AI-generated masks:

# Generate mask using ComfyUI or other tool
python3 extract_mask.py "the wooden chest" scene.png chest_mask.png

# Add to ORA
python3 ora_edit.py mask_element scene.ora \
    --mask chest_mask.png \
    --entity "chest" \
    --layer "background"

Example 4: Iterative Design

Refining elements with multiple mask attempts:

# First iteration
python3 ora_edit.py mask_element scene.ora \
    --mask door_v1.png \
    --entity "door" \
    --layer "background"

# Second iteration (creates door_1)
python3 ora_edit.py mask_element scene.ora \
    --mask door_v2.png \
    --entity "door" \
    --layer "background"

# Third iteration (creates door_2)
python3 ora_edit.py mask_element scene.ora \
    --mask door_v3.png \
    --entity "door" \
    --layer "background"

The ORA now contains all three versions to compare in GIMP/Krita.

Example 5: Layer-Based Masking

Using different source layers for different entities:

# Create ORA with multiple base layers
python3 ora_edit.py create day_scene.png scene.ora --layer-name "day"
python3 ora_edit.py create night_scene.png scene_night.ora --layer-name "night"

# Extract and use specific layers
# (Assume we've combined these into one ORA manually or via script)

# Mask using day layer
python3 ora_edit.py mask_element scene.ora \
    --mask sun_mask.png \
    --entity "sun" \
    --layer "day"

# Mask using night layer
python3 ora_edit.py mask_element scene.ora \
    --mask moon_mask.png \
    --entity "moon" \
    --layer "night"

Example 6: Exporting Layers for External Use

Extracting layers for use in other tools or workflows:

# Check what layers exist
python3 ora_edit.py inspect character.ora

# Extract specific animation frames
python3 ora_edit.py extract_png character.ora --layer arm_0 --output arm_frame1.png
python3 ora_edit.py extract_png character.ora --layer arm_1 --output arm_frame2.png

# Extract background for compositing
python3 ora_edit.py extract_png scene.ora --layer background --output bg_composite.png

Command Reference

create

Create an ORA file from a PNG image.

positional arguments:
  input_png             Input PNG file
  output_ora            Output ORA file (default: same name with .ora extension)

options:
  -h, --help            Show help message
  --layer-name NAME     Name for the root layer (default: base)

mask_element

Create a masked layer for an entity.

positional arguments:
  input                 Input ORA or PNG file

options:
  -h, --help            Show help message
  --mask MASK           Mask file to use as alpha channel (required)
  --entity ENTITY       Entity name/group name (required)
  --layer LAYER         Source layer to copy and mask (default: base)
  --output OUTPUT       Output ORA file (default: same as input)

Important behaviors:

  • If input is PNG: Automatically converts to ORA first, using "base" as the layer name
  • Entity groups are created above base layers in the stack
  • Layer names auto-increment within groups (entity_0, entity_1, ...)
  • If the specified --layer doesn't exist, the command errors and lists available layers

inspect

Display the structure of an ORA file without modifying it.

positional arguments:
  ora_file              ORA file to inspect

options:
  -h, --help            Show help message

Output includes:

  • File path
  • Entity groups with their layer counts
  • Base layers
  • Total layer/group statistics

extract_png

Extract a layer from an ORA file as a PNG image.

positional arguments:
  ora_file              ORA file to extract from

options:
  -h, --help            Show help message
  --layer LAYER         Name of the layer to extract (required)
  --output OUTPUT       Output PNG file (default: <layer_name>.png)

Use cases:

  • Export layers for use in other graphics applications
  • Extract masked elements for game development
  • Create individual assets from composed ORA files
  • Backup or archive specific layers

Important behaviors:

  • If the specified --layer doesn't exist, the command errors and lists available layers
  • Output defaults to <layer_name>.png if not specified
  • Preserves transparency (RGBA) from the original layer

Tips

Mask Requirements

  • Masks can be grayscale (L mode) or RGB/RGBA
  • White = fully opaque, Black = fully transparent
  • Grayscale values create partial transparency

Layer Organization

  • Entity groups appear first in the layer stack
  • Base layers appear at the end
  • This organization makes it easy to toggle entities on/off in GIMP/Krita

Workflow Integration

  • Combine with extract_mask.py for AI-powered masking
  • Use mask_to_polygon.py to convert masks to Godot collision polygons
  • Chain multiple mask_element calls in shell scripts for batch processing

Error Handling

The tool provides clear error messages:

# Missing layer
$ python3 ora_edit.py mask_element scene.ora --mask x.png --entity door --layer "missing"
Error: Layer 'missing' not found in ORA file
Available layers:
  - base
  - door_0
  - door_1

Dependencies

  • Python 3.8+
  • Pillow (PIL)

Install dependencies:

pip install Pillow

ORA Format

OpenRaster (.ora) is an open standard for layered raster graphics. This tool creates ORA 0.0.3 compatible files that can be opened in:

  • GIMP (with ora plugin)
  • Krita
  • MyPaint
  • Other ORA-supporting applications

The generated structure:

archive.ora/
├── mimetype              # "image/openraster"
├── stack.xml            # Layer hierarchy
├── mergedimage.png      # Flattened preview
├── Thumbnails/
│   └── thumbnail.png    # 256x256 preview
└── data/
    ├── base.png         # Layer images
    └── entity/
        └── entity_0.png