Files
Video-Processing-Scripts/video-processing-scripts/Clone-Image.md
T

13 KiB

Clone-Image.ps1

Clones (copies) an image file using ffmpeg with optional resizing, quality and compression settings. Reads PNG, JPEG, WEBP, BMP, AVIF and TIFF sources and writes to any of those formats depending on the -Target file extension.

Synopsis

The output format is chosen from the -Target extension (.png, .jpg/.jpeg, .webp, .bmp, .avif, .tif/.tiff; defaults to .png when no recognised extension is given). Each format has its own encoder profile — the script picks the appropriate ffmpeg encoder and applies any quality/compression settings. See Output formats for the full matrix.

When -Size is provided, the source image is resized using a cover-then-crop strategy:

  1. The image is scaled (preserving its original pixel aspect ratio) so it fully covers the requested width and height — one dimension matches exactly, the other overflows.
  2. The overflowing dimension is then centre-cropped so the final image is exactly the requested size.

The source aspect ratio is preserved at all times (no warping/stretching).

Parameters

  • -Source (required): Path to input image file. Accepted formats: .png, .jpg, .jpeg, .webp, .bmp, .avif, .tif, .tiff. If the path has no extension, the script tries each supported extension in turn.
  • -Target (required): Path to output image file. The extension picks the output format (PNG, JPEG, WEBP, BMP, AVIF, or TIFF). If the extension is missing or unrecognised, .png is appended and the PNG profile is used.
  • -Size (optional): Size of the output image. Uses the source image's size if not specified. Possible values: 480p, 720p, 1080p, HD, 1440p, 2K, 2160p, 4K, or custom size in format width:height. When specified, the source is cover-scaled (aspect ratio preserved) so it fully covers the requested dimensions, then centre-cropped to the exact target size. No image warping.
  • -Quality (optional): Quality factor for lossy output formats (JPEG, WEBP, AVIF). Lower values mean better quality (consistent across all three formats). Ignored for PNG, BMP and TIFF (lossless).
    • JPEG: passed to ffmpeg's -q:v (typical range 1-31, lower = better).
    • WEBP: inverted internally and passed to libwebp's -quality (0-100, higher = better), so the "lower = better" semantic is preserved from the caller's perspective.
    • AVIF: passed to libaom-av1's -crf (0-63, lower = better).
  • -Compression (optional): Compression level for PNG and WEBP outputs.
    • PNG: libpng's -compression_level (0-9, higher = smaller files / slower encoding).
    • WEBP: libwebp's -compression_level (0-6, higher = smaller files / slower encoding).
    • Ignored for JPEG, AVIF, BMP and TIFF.
  • -Metadata: Copy available metadata from source image file to target image file.
  • -Upscale (optional): Upscale factor (2, 3 or 4) applied to the source image with upscayl-bin.exe before ffmpeg runs. The upscaled image is written to a Windows temp PNG (under %TEMP%) and used as the ffmpeg input, so any -Size / -LTX cover-scale-then-crop is applied to the already-upscaled image. The temp PNG is deleted automatically when the script finishes. Requires upscayl-bin.exe in PATH and the UPSCAYL_HOME and NCNN_GPU_ID environment variables (see index). Omit (or pass 0) to disable upscaling.
  • -Model (optional): Upscayl model name to use when -Upscale is specified. Defaults to 4xNomos8kSC. The model files (<Model>.bin and <Model>.param) must exist under %UPSCAYL_HOME%\models (see the Upscalers installation guide for installing additional models). Ignored when -Upscale is not specified.
  • -Keep (optional): Path at which to save a copy of the upscayl-bin output (i.e. the upscaled image, before ffmpeg's cover-scale-then-crop). The file extension picks the format (.png, .jpg/.jpeg, .webp, .bmp, .avif, .tif/.tiff); if the extension is missing or unrecognised, .png is appended. When the requested format is .png (the upscayl native output) the temp file is simply copied; otherwise it is converted with ffmpeg using the same per-format encoders as -Target (with default quality settings). Only valid when -Upscale is specified — it is ignored (with a warning) otherwise.
  • -LTX: Override the dimensions chosen by -Size with the closest LTX-2 (Wan2GP by DeepBeepMeep) canonical resolution for the source's aspect ratio. Only valid when -Size is one of HD, 1080p, 720p or 480p. The script probes the source's width/height, computes its aspect ratio, and picks the bucket whose ratio is numerically closest. Cover-scale-then-centre-crop still applies, so the source is fitted to the picked LTX dimensions without warping. The buckets per -Size are:
    • HD / 1080p: 1920x1088 (16:9), 1088x1920 (9:16), 1664x960 (21:9), 960x1664 (9:21).
    • 720p: 1280x704 (16:9), 704x1280 (9:16), 1088x576 (21:9), 576x1088 (9:21).
    • 480p: 832x448 (16:9), 448x832 (9:16), 896x512 (4:3), 512x896 (3:4).

Examples

Clone entire image (same size, same format):

.\Clone-Image.ps1 -Source photo.png -Target output.png

Convert PNG to JPEG with default quality:

.\Clone-Image.ps1 -Source photo.png -Target photo.jpg

Convert with custom JPEG quality (lower = better):

.\Clone-Image.ps1 -Source photo.png -Target photo.jpg -Quality 3
# Uses ffmpeg -q:v 3

Convert to WEBP at high quality:

.\Clone-Image.ps1 -Source photo.png -Target photo.webp -Quality 10
# Internally maps to libwebp -quality 90 (100 - 10)

Convert to AVIF at near-visually-lossless:

.\Clone-Image.ps1 -Source photo.png -Target photo.avif -Quality 18
# Uses libaom-av1 -crf 18 -still-picture 1

Upscale 4x with the default model, then crop to 4K:

.\Clone-Image.ps1 -Source small.jpg -Target big_4k.png -Upscale 4 -Size 4K
# small.jpg is upscaled x4 with 4xNomos8kSC into a temp PNG;
# ffmpeg then cover-scales the upscaled image and centre-crops to 3840x2160.

Upscale 2x with a custom model:

.\Clone-Image.ps1 -Source photo.png -Target photo_2x.png -Upscale 2 -Model 4xUltraSharp
# Requires 4xUltraSharp.bin and 4xUltraSharp.param under %UPSCAYL_HOME%\models.

Upscale 4x to a JPEG with custom quality:

.\Clone-Image.ps1 -Source thumb.jpg -Target thumb_hi.jpg -Upscale 4 -Quality 3

Upscale 4x and also keep the full-resolution upscaled PNG:

.\Clone-Image.ps1 -Source small.jpg -Target small_4k.png -Upscale 4 -Size 4K -Keep small_upscaled.png
# small_upscaled.png is the raw upscayl output (no crop); small_4k.png is cover-scaled+cropped to 3840x2160.

Upscale and keep the upscaled image as JPEG (format conversion via ffmpeg):

.\Clone-Image.ps1 -Source photo.png -Target photo_2x.png -Upscale 2 -Keep photo_upscaled.jpg
# upscayl writes a PNG; ffmpeg converts that PNG to photo_upscaled.jpg before the main clone step.

Resize using a named preset (cover-scale then crop):

.\Clone-Image.ps1 -Source photo.png -Target photo_720.png -Size 720p
# Scales the source so it fully covers 1280x720, then centre-crops to exactly 1280x720.

Pick the closest LTX-2 720p bucket from a 16:9 source:

.\Clone-Image.ps1 -Source landscape.png -Target landscape_ltx720.png -Size 720p -LTX
# A 1920x1080 (16:9) source is fitted to 1280x704.

Pick the closest LTX-2 1080p bucket from a 9:16 phone shot:

.\Clone-Image.ps1 -Source portrait.jpg -Target portrait_ltx1080.png -Size 1080p -LTX
# A 1080x1920 (9:16) source is fitted to 1088x1920.

Pick the closest LTX-2 480p bucket from a 4:3 source:

.\Clone-Image.ps1 -Source legacy.jpg -Target legacy_ltx480.png -Size 480p -LTX
# A 1024x768 (4:3) source is fitted to 896x512.

Resize with a custom resolution:

.\Clone-Image.ps1 -Source photo.png -Target square.jpg -Size 1024:1024
# Scales so the image fully covers 1024x1024, then centre-crops to a square.

Maximum PNG compression:

.\Clone-Image.ps1 -Source photo.png -Target small.png -Compression 9

WEBP with explicit quality and compression effort:

.\Clone-Image.ps1 -Source photo.png -Target photo.webp -Quality 20 -Compression 6
# libwebp -quality 80 -compression_level 6

Preserve metadata when converting formats:

.\Clone-Image.ps1 -Source photo.jpg -Target photo.webp -Metadata
# Copies EXIF/XMP/etc. that ffmpeg can transport into the WEBP container.

Using absolute paths:

.\Clone-Image.ps1 -Source "C:\Photos\input.png" -Target "D:\Output\result.jpg"

Output formats

The output format is selected from the -Target file extension. Each format has its own ffmpeg encoder and the parameters that apply to it.

Format Target extension(s) ffmpeg encoder Lossy? -Quality applies -Compression applies
PNG .png (default) png No No Yes (0-9, higher = smaller)
JPEG .jpg, .jpeg mjpeg (yuvj420p) Yes Yes (1-31, lower = better) No
WEBP .webp libwebp Yes Yes (inverted: 0-100, lower = better) Yes (0-6, higher = smaller)
AVIF .avif libaom-av1 (still-picture) Yes Yes (0-63, lower = better) No
BMP .bmp bmp No No No
TIFF .tif, .tiff tiff No No No

General rules

  • The output format is determined entirely by the -Target extension. If -Target has no extension (or an unrecognised one), .png is appended and the PNG profile is used.
  • Resizing always uses the cover-scale then centre-crop strategy. The source pixel aspect ratio is preserved (no warping). When -Size is omitted, the source dimensions are kept as-is.
  • -Quality and -Compression are interpreted in a format-agnostic way from the caller's perspective: lower -Quality always means better quality, and higher -Compression always means smaller files. Per-format ffmpeg mappings (including the libwebp -quality inversion) happen inside the script.
  • Defaults when -Quality/-Compression are omitted: JPEG uses -q:v 2, WEBP uses -quality 90, AVIF uses -crf 25. PNG and lossless formats are encoded with ffmpeg's default settings.
  • AVIF output uses libaom-av1 with -still-picture 1 and -cpu-used 4 for a reasonable speed/quality tradeoff. Your ffmpeg build must include libaom-av1 for .avif output to work.
  • -Metadata toggles ffmpeg's -map_metadata 0 (copy) vs -map_metadata -1 (strip). Which metadata actually survives the conversion depends on what the source and target formats can carry.
  • -LTX only takes effect when -Size is HD, 1080p, 720p or 480p. Combining it with any other -Size value (or omitting -Size) is rejected with an explicit error so the user is never silently downgraded to the regular preset.
  • -Upscale runs upscayl-bin.exe before ffmpeg. The script validates that upscayl-bin.exe is on PATH, that UPSCAYL_HOME is set and exists, that the models subfolder and the requested <Model>.bin / <Model>.param files are present, and that NCNN_GPU_ID is set to a valid integer (0+ for a GPU index; -1 omits the -g flag, so upscayl-bin uses its default device, which is not necessarily the CPU). The intermediate upscaled PNG is created under %TEMP% and deleted after the run (including on ffmpeg failure).
  • -Keep saves the raw upscayl output (no cropping/scaling). When the -Keep extension is .png, the temp file is copied directly (no re-encode); for any other supported extension a separate ffmpeg invocation converts the PNG to the requested format with default quality settings (JPEG -q:v 2, WEBP -quality 90, AVIF -crf 25). -Keep is ignored with a warning if -Upscale is not specified.

Notes

  • AVIF encoding is slow. libaom-av1 is significantly slower than the other encoders even with -cpu-used 4. WebP at high -Compression is also slower than PNG or JPEG.
  • JPEG output is always 4:2:0 chroma (yuvj420p). If you need 4:4:4 JPEG or 16-bit output, edit the encoder args directly.
  • TIFF and BMP are stored uncompressed (TIFF can be configured for LZW/Deflate via additional ffmpeg options if needed).

Existing Files

  • An existing -Target image is replaced without a prompt. ffmpeg runs with -y, so the old file is lost. Use -WhatIf first, or write to a new name.
  • An existing file at -Keep is replaced in the same way.
  • The folders that contain -Target and -Keep must already exist. The script stops with an error instead of creating them.
  • The temporary upscaled PNG is deleted when the script finishes.

Safe Execution

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

  • -WhatIf: Simulate the operation without actually creating files. Shows what would be done.
  • -Confirm: Prompt for confirmation before each state-changing operation.

Simulate without making changes:

.\Clone-Image.ps1 -Source photo.png -Target output.jpg -WhatIf

Prompt before creating files:

.\Clone-Image.ps1 -Source photo.png -Target output.avif -Confirm