Skip to main content
Trimming removes transparent borders from sprites before packing. Smaller packed rects mean a denser atlas and less wasted GPU texture memory. The original sprite dimensions and the trim offset are stored in the data file so engines can reconstruct the sprite at its correct screen position.

Trim modes

No pixels are removed. The full source image is packed as-is. No trim metadata is written to the data file.
[sprites]
trim_mode = "none"

Configuration

[sprites]
trim_mode = "trim"         # none | trim | crop | crop-keep-pos | polygon
trim_threshold = 1         # pixels with alpha <= this value are transparent (0–255)
trim_margin = 0            # transparent pixels to keep around the trimmed edge
common_divisor_x = 0       # round trimmed width up to nearest multiple (0 = disabled)
common_divisor_y = 0       # round trimmed height up to nearest multiple (0 = disabled)

Examples

Keep transparent margin

Keep a 2-pixel transparent margin around every trimmed sprite:
[sprites]
trim_mode = "trim"
trim_margin = 2
This is useful when sprites have soft edges or glow effects that you want to preserve.

Ensure divisible dimensions

Ensure all trimmed widths are multiples of 4 (required for some texture formats):
[sprites]
trim_mode = "trim"
common_divisor_x = 4
common_divisor_y = 4

Adjust alpha threshold

Treat pixels with alpha ≤ 10 as transparent:
[sprites]
trim_mode = "trim"
trim_threshold = 10
The default threshold of 1 works for most sprites. Increase it if your sprites have faint semi-transparent edges you want to remove.

Technical details

The bounding box scan visits every pixel once. For each pixel, the alpha channel is compared against trim_threshold. Pixels with alpha strictly greater than the threshold are considered opaque. After the bounding box is found, trim_margin is added on all four sides and the result is clamped to the image dimensions. common_divisor_x/y then expands the width/height to the next valid multiple, expanding toward the right/bottom edge and clamping again. For polygon mode, after the image is cropped to the bounding box, all opaque pixels are collected into a point set and the convex hull is computed via the geo crate. Hull vertices are in the trimmed image’s local pixel space (origin at the top-left of the packed frame). The hull is stored in Sprite::polygon and copied verbatim into AtlasFrame::polygon in the data output. The Sprite::original_size field records the pre-trim dimensions and is never changed by this stage.

Data file output

When trimming is enabled, each frame in the data file includes:
{
  "frame": { "x": 10, "y": 20, "w": 48, "h": 48 },
  "spriteSourceSize": { "x": 8, "y": 8, "w": 48, "h": 48 },
  "sourceSize": { "w": 64, "h": 64 }
}
  • frame — Position and size in the atlas (trimmed)
  • spriteSourceSize — Position and size of the trimmed region within the original image
  • sourceSize — Original image dimensions before trimming
FastPack’s trim mode maps to TexturePacker’s “Trim” sprite mesh type. TexturePacker’s “Crop” maps to crop. The trim_threshold is equivalent to TexturePacker’s alpha threshold setting. trim_margin is equivalent to TexturePacker’s “border padding” on the sprite level (not to be confused with atlas-level border padding).

Build docs developers (and LLMs) love