- compose(): scales print to TransformState.width/height, rotates
clockwise by TransformState.rotation (negated for Pillow), pastes
onto a transparent layer via alpha_composite, saves PNG or JPG
- Rotation centre fixed at print bounding-box centre; paste_x/y
computed from centre - rotated_size/2 per design doc §13.3
- JPG: flattens RGBA onto white RGB background before saving
- Out-of-bounds print clips silently via PIL paste; width/height<=0
returns ComposeResult(success=False); file errors caught, never raise
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- BUILTIN_TEMPLATES: 4 presets (正方形/纵向/横向长方形/左胸小号)
- load_custom_templates(): reads templates.json, skips corrupt entries
individually so one bad record never blocks the rest
- get_all_templates(): builtin first, then custom
- add_template(): upsert by name, forces type="custom"
- rename_template() / delete_template(): raise ValueError if not found
- _save_custom_templates(): auto-creates config/ dir, logs on failure
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Template, ExportOptions, BatchMode, BatchOptions, ComposeResult,
BatchResult to models.py. Keep existing ImageAsset and TransformState,
adding center() helper to TransformState.
Template uses ratio-based fields with to_transform_state() to convert
to pixel coordinates for any garment size.
BatchMode enum covers all four batch modes from PRD.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- DEFAULT_CONFIG defines output_format, output_quality, output_dir,
last_garment_dir, last_print_dir
- load_config(): merges file values with defaults; never raises on
missing, damaged, or non-object JSON root
- save_config(): creates config/ dir as needed; logs error on failure
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- get_app_dir(): project root in dev, exe dir in PyInstaller bundle
- get_resource_path/get_config_path: paths under app dir
- get_log_dir/get_output_dir: auto-create and return logs/ and output/
- Refactor log_service to use get_log_dir() instead of own __file__ calc
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- setup_logging() creates logs/ dir and writes timestamped log file
- format: asctime name levelname message
- falls back to console-only if log dir is not writable
- main.py now calls setup_logging() at startup and logs app name/version
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>