Files
Video-Processing-Scripts/video-processing-scripts/Create-Turnaround.md
T

12 KiB
Raw Blame History

Create-Turnaround.ps1

Combines a sequence of images into a single turnaround (character reference sheet) image using ffmpeg.

A turnaround image shows the same subject from several angles — typically front, 3/4, profile and back — side by side at a consistent scale, in one wide image. It is the usual input for keeping a character consistent across image and video generation models.

Synopsis

All images found at -Source are placed side by side, left to right, in the order given by a numeric-aware sort of their file names. -Target is optional: without it the sheet is saved as a JPEG named after the source directory, in the current directory. Every image keeps its original pixels: nothing is scaled, stretched or cropped. Images smaller than the largest one are centred in their cell and padded with -Background (white by default), so a set of slightly different sizes still produces a clean, aligned sheet.

Supports PNG, JPEG, WEBP, BMP, AVIF and TIFF for both input and output.

Parameters

  • -Source (required): Directory containing the images, a file pattern (e.g. Img*.jpg), or a single image file. Can be absolute or relative to the current directory. Non-recursive; only supported image extensions are considered.
  • -Target (optional): Path to the output turnaround image. Can be absolute or relative to the current directory. The extension selects the output format; .png is appended when the extension is missing or unrecognised. When omitted, the name is derived from the source — see Default Target Name.
  • -Rows (optional): Number of rows to arrange the images in. Defaults to 1 (a single horizontal row). When only -Rows is given, the column count is computed as ceil(imageCount / Rows).
  • -Columns (optional): Number of columns to arrange the images in. When only -Columns is given, the row count is computed as ceil(imageCount / Columns). When both are given, Rows × Columns must be at least the number of images.
  • -Background (optional): Colour used to pad images smaller than the largest one, and to fill the unused cells of an incomplete last row. Defaults to white. Accepts any ffmpeg colour: a name (white, black, silver), 0xRRGGBB, or name@alpha (white@0 for transparent).
  • -Quality (optional): Quality factor for the lossy output formats (jpeg, webp, avif). Lower values mean better quality in all three, see Quality and Compression. Ignored (with a warning) for png, bmp and tiff.
  • -Compression (optional): Compression level for png (0-9) and webp (0-6); higher means smaller files but slower encoding. Ignored (with a warning) for jpeg, avif, bmp and tiff.

Default Target Name

When -Target is omitted, the script writes a JPEG named after the last directory member of the source, into the current directory:

-Source Name taken from Result (run from C:\work)
A directory, e.g. C:\renders\CharacterA The last member of that directory's full path C:\work\CharacterA.jpg
A file pattern, e.g. Img*.jpg The last member of the current directory's full path C:\work\work.jpg
A single image file The last member of the current directory's full path C:\work\work.jpg

Relative sources are resolved to a full path first, so -Source . run from C:\renders\CharacterA produces CharacterA.jpg in that same directory. Trailing separators are ignored (C:\renders\CharacterA\ behaves identically).

Since the derived name always ends in .jpg, the output uses the JPEG encoder and its default -q:v 2; add -Quality to change it, or pass -Target explicitly for a different format.

PS C:\work> .\Create-Turnaround.ps1 -Source C:\renders\CharacterA
No -Target specified; using C:\work\CharacterA.jpg

Drive-root error

A path with no directory member cannot name the file, so a drive root is rejected:

PS C:\work> .\Create-Turnaround.ps1 -Source "C:\"
Cannot derive a target file name from 'C:\': the path is a drive root with no directory member. Specify -Target explicitly.

The same applies when -Source is a file pattern and the current directory is a drive root (e.g. running Create-Turnaround.ps1 -Source *.png from C:\). Supply -Target explicitly in that case.

Image Order

File names are sorted with a numeric-aware (natural) sort, so digit runs compare as numbers:

Img1.png, Img2.png, Img10.png      (not Img1, Img10, Img2)
Frame-00001.png ... Frame-00012.png

Zero-padded sequence names therefore sort identically to a plain alphabetical sort, while non-padded names (Pose2, Pose10) still come out in the intended order.

Cell Size and Padding

The cell is as large as the largest source image in both dimensions:

  • cellWidth = max width of all sources
  • cellHeight = max height of all sources
  • Output size = cellWidth × columns by cellHeight × rows

Each image is centred in its cell. Images that already match the cell size are passed through untouched; smaller ones gain -Background margins. No source image is ever resized, so the sheet is lossless with respect to the originals (verified at PSNR = ∞ for PNG in/PNG out).

When padding is applied, the console reports it:

  Cell size: 600x768
  Note: 2 image(s) smaller than the largest image; centred and padded with white.

Layout

Single row (default)

Four 512x768 images produce a 2048x768 sheet:

[1][2][3][4]

Grid

-Rows and/or -Columns wrap the images into a grid. With 4 images and -Columns 2 (→ 2 rows), the output is 1024x1536:

[1][2]
[3][4]

An incomplete last row is centred inside the full output width and the remaining space filled with -Background. With 4 images and -Columns 3 (→ 2 rows, 1536x1536):

[1][2][3]
   [4]
Images Switches Rows x Columns Output (512x768 cells)
4 (none) 1 x 4 2048x768
4 -Columns 2 2 x 2 1024x1536
4 -Rows 2 2 x 2 1024x1536
4 -Columns 3 2 x 3 1536x1536 (last row centred)
4 -Rows 1 -Columns 2 — Error: 2 cells is not enough for 4 images

Output Format

The target extension selects the encoder, with the same mapping and defaults as Clone-Image.ps1:

Extension Encoder Default settings -Quality -Compression
.png png Lossless — -compression_level (0-9)
.jpg / .jpeg mjpeg -q:v 2, yuvj420p -q:v (1-31) —
.webp libwebp -quality 90 -quality (inverted) -compression_level (0-6)
.avif libaom-av1 -still-picture 1, -cpu-used 4, -crf 25 -crf (0-63) —
.bmp bmp Lossless — —
.tif / .tiff tiff Lossless — —

PNG is recommended for a turnaround sheet that will be fed back into a generation model, since it is lossless and preserves transparency.

Quality and Compression

-Quality is always interpreted as lower = better quality, regardless of format. For webp — whose native -quality option means the opposite — the value is inverted internally (-Quality 20 becomes -quality 80), so a single convention holds across jpeg, webp and avif.

Format -Quality maps to Range Default when omitted
jpeg -q:v 1-31 (lower is better) 2
webp -quality = 100 - Quality 0-100 after inversion 90 (i.e. -Quality 10)
avif -crf 0-63 (lower is better) 25

-Compression trades encoding time for file size on the two formats that support it, and does not affect image quality (both are lossless/independent of it):

Format -Compression maps to Range
png -compression_level 0-9 (higher = smaller, slower)
webp -compression_level 0-6 (higher = smaller, slower)

Measured on a 3840x480 sheet:

Command Output size
-Target sheet.jpg (default) 73,744 B
-Target sheet.jpg -Quality 2 73,744 B (identical to the default)
-Target sheet.jpg -Quality 28 33,349 B
-Target sheet.webp -Quality 5 30,508 B
-Target sheet.webp -Quality 70 17,578 B
-Target sheet.png -Compression 0 7,395,829 B
-Target sheet.png -Compression 9 10,990 B

Passing -Quality to a lossless format (or -Compression to a format that ignores it) is not an error; the value is dropped and a warning is printed:

WARNING: -Quality is ignored for the lossless png format.

Examples

No -Target — JPEG named after the source directory, written to the current directory:

.\Create-Turnaround.ps1 -Source C:\renders\CharacterA
# Writes .\CharacterA.jpg

No -Target, run from inside the frames directory:

cd C:\renders\CharacterA
.\Create-Turnaround.ps1 -Source "F*.png"
# Writes C:\renders\CharacterA\CharacterA.jpg (name taken from the current directory)

Four frames in a directory into a single-row sheet:

.\Create-Turnaround.ps1 -Source .\renders -Target turnaround.png

Using a file pattern:

.\Create-Turnaround.ps1 -Source ".\renders\Img*.jpg" -Target turnaround.png

Extension-less target (.png is appended):

.\Create-Turnaround.ps1 -Source .\renders -Target character-sheet
# Writes character-sheet.png

Eight angles as a 2x4 grid:

.\Create-Turnaround.ps1 -Source .\renders -Target turnaround.png -Rows 2

Three columns, incomplete last row centred:

.\Create-Turnaround.ps1 -Source .\renders -Target turnaround.png -Columns 3

Transparent background instead of white:

.\Create-Turnaround.ps1 -Source .\renders -Target turnaround.png -Background "white@0"

Mid-gray background, JPEG output:

.\Create-Turnaround.ps1 -Source .\renders -Target turnaround.jpg -Background 0x808080

Smaller JPEG sheet (lower quality):

.\Create-Turnaround.ps1 -Source .\renders -Target turnaround.jpg -Quality 20

Maximum PNG compression (smallest lossless file, slowest encode):

.\Create-Turnaround.ps1 -Source .\renders -Target turnaround.png -Compression 9

Near-lossless webp with maximum compression effort:

.\Create-Turnaround.ps1 -Source .\renders -Target turnaround.webp -Quality 1 -Compression 6

Existing Files

An existing -Target image is replaced without a prompt. ffmpeg runs with -y.

  • The folder that contains -Target must already exist. The script stops with an error instead of creating it.
  • Use -WhatIf first, or write to a new name.

Safe Execution

This script supports -WhatIf and -Confirm for safe execution:

  • -WhatIf: Prints the image list, the computed layout and the full ffmpeg command without writing the output file.
  • -Confirm: Prompts for confirmation before creating the turnaround image.
.\Create-Turnaround.ps1 -Source .\renders -Target turnaround.png -WhatIf

Notes

  • Requires ffmpeg and ffprobe in the Windows PATH.
  • The target directory must exist; the script errors out rather than creating it.
  • Every input is normalised to rgba before stacking, so sources may mix formats (e.g. PNG + JPEG + WEBP) and colour models freely.
  • Source images are never scaled, stretched or cropped — differing sizes are reconciled with padding only.
  • A single image is valid input and produces a one-cell output (useful to normalise/convert a frame).
  • Files that are not recognised images are ignored; if none remain, the script errors with the list of supported extensions.
  • The output file is excluded from its own input list, so writing -Target into the -Source directory stays idempotent across re-runs (the previous sheet is not stacked into the new one).