Skip to content

feat(nodes): add Save Image (Gallery + File Export) node#9077

Open
Pfannkuchensack wants to merge 5 commits intomainfrom
feat/image-save-filename-control
Open

feat(nodes): add Save Image (Gallery + File Export) node#9077
Pfannkuchensack wants to merge 5 commits intomainfrom
feat/image-save-filename-control

Conversation

@Pfannkuchensack
Copy link
Copy Markdown
Collaborator

@Pfannkuchensack Pfannkuchensack commented Apr 20, 2026

Summary

Adds a new invocation Save Image (Gallery + File Export) (save_image_to_file) that saves an image to the gallery like the standard Save Image node and additionally writes a copy to the filesystem with a customizable filename built from a prefix and suffix around the gallery UUID.

  • Filename pattern: {prefix}{uuid}{suffix}.{png|jpg|webp}
  • The UUID matches the gallery entry, so exported files can always be matched back to the gallery item.
  • Quality input (1–100) for JPG/WEBP, ignored for PNG.
  • Board and Metadata inputs behave exactly like the standard Save Image node (via WithBoard / WithMetadata mixins).
  • Output directory is restricted to subfolders of the configured InvokeAI outputs folder. Absolute paths (D:/..., /etc/...) and path traversal (..) are rejected with a clear ValueError.
  • Missing subdirectories are created automatically.
image

Example

Input Value
prefix hero_
suffix _final
file_format png
output_directory exports/2026

Result on disk: <outputs>/exports/2026/hero_<uuid>_final.png
Gallery entry: <uuid>.png (unchanged)

Related Issues / Discussions

Closes #8372

QA Instructions

  1. Start InvokeAI and open the Workflow Editor.
  2. Add the new node Save Image (Gallery + File Export) (category: image).
  3. Connect any image source (e.g. a generation output) to its image input.
  4. Default behavior:
    • Leave output_directory, prefix, suffix empty, file_format = png.
    • Run the workflow.
    • Verify a file <uuid>.png exists in the configured outputs folder.
    • Verify the image also appears in the gallery (or on the selected board).
  5. Prefix / suffix:
    • Set prefix = "test_", suffix = "_v1", run again.
    • Verify <outputs>/test_<uuid>_v1.png exists.
  6. Subfolder:
    • Set output_directory = "my-exports/sub", run again.
    • Verify <outputs>/my-exports/sub/<uuid>.png exists and that the directory was created automatically.
  7. JPG quality:
    • Set file_format = jpg, quality = 60, use an image with alpha.
    • Verify the file is saved as JPEG (RGB, no alpha), at a lower quality than a second run with quality = 95.
  8. WEBP: Repeat with file_format = webp.
  9. Security — absolute path:
    • Set output_directory = "D:/some/path" (or /tmp/foo on Linux).
    • Verify the node fails with an error mentioning “Absolute paths are not allowed”.
  10. Security — path traversal:
    • Set output_directory = "../outside" or "subdir/../../outside".
    • Verify the node fails with an error about staying within the outputs folder.
  11. Board / Metadata: Set a board and/or metadata and verify they are applied to the gallery entry (standard Save Image behavior).

Automated tests

20 unit tests are included in tests/app/invocations/test_save_image_to_file.py covering:

  • Gallery save is invoked
  • Default directory, relative subfolders, nested paths
  • Prefix / suffix combinations (both, prefix only, suffix only)
  • Filename uses the gallery UUID (not the input UUID)
  • Absolute paths rejected (D:/, C:/, /etc, /tmp)
  • Path traversal rejected (.., subdir/../../outside)
  • PNG preserves alpha, JPG converts RGBA → RGB, WEBP works
  • quality bounds (1–100) enforced by pydantic
  • Output is a pass-through of the gallery image_dto

Run with:

uv run --extra cuda pytest tests/app/invocations/test_save_image_to_file.py -v

Merge Plan

Standard merge.

Checklist

  • The PR has a short but descriptive title, suitable for a changelog
  • Tests added / updated (if applicable)
  • ❗Changes to a redux slice have a corresponding migration — N/A
  • Documentation added / updated (if applicable) — N/A (node is self-documenting via rich field descriptions)
  • Updated What's New copy (if doing a release after this PR) — to be decided at release time

Saves an image to the gallery and additionally exports a copy to the
filesystem with a custom filename using prefix and suffix around the
gallery UUID.

- Filename pattern: {prefix}{uuid}{suffix}.{png|jpg|webp}
- UUID matches the gallery entry so exported files can be matched back
- Quality input (1-100) for JPG/WEBP, ignored for PNG
- Board and Metadata inputs behave like the standard Save Image node
- Output directory restricted to subfolders of the InvokeAI outputs
  folder; absolute paths and path traversal are rejected
@github-actions github-actions Bot added python PRs that change python files invocations PRs that change invocations python-tests PRs that change python tests labels Apr 20, 2026
@github-actions github-actions Bot added the frontend PRs that change frontend files label Apr 20, 2026
@lstein lstein added the 6.14.x label Apr 25, 2026
@lstein lstein moved this to 6.14.x Theme: LIBRARY UPDATES in Invoke - Community Roadmap Apr 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.14.x frontend PRs that change frontend files invocations PRs that change invocations python PRs that change python files python-tests PRs that change python tests

Projects

Status: 6.14.x Theme: LIBRARY UPDATES

Development

Successfully merging this pull request may close these issues.

[enhancement]: File naming in nodes.

3 participants