trebeljahr/sprite-tools
v0.1.0
Generate video with your local provider keys and export transparent sprite sheets with collision metadata.
Changelog
All notable changes to sprite-tools will be documented here.
This project follows semantic versioning for the npm package.
[Unreleased]
- Add a Nine-slice tool at
/nine-slice— set the four border insets by hand or start from a detected guess, then check them against a live stretched preview at any target size. - Add the
nine-sliceCLI command, thesprite_generate_nine_sliceMCP tool, and anineSlicesection inmeta, all emitting the same insets and nine region rects. - Add Android
.9.pngimport and export, so a marker-border patch can be decoded into insets and insets can be written back out as a.9.png. One contiguous stretch run per edge is supported. - Add an Outline & Shadow tool at
/outline— outer or inner outlines at an exact pixel width, with 4- or 8-neighbour growth, plus an offset, blurred drop shadow, on a single sprite or every cell of a sheet. - Add the
outlineCLI command and thesprite_add_outline/sprite_add_shadowMCP tools, sharing the web app's distance-transform pass and defaults. - Re-tint a whole shading ramp at once instead of swapping its shades one by one — the Palette tab now detects the ramps in a sprite's palette and remaps each one as a unit, preserving the lightness steps, the relative saturation, and the shadow-to-highlight hue drift that make the shading read.
- Generate named recolor variants from a single sheet: an evenly spaced hue set (2–12 tints, the original included) or a hand-written variant list, previewed side by side and exported as
<base>_<slug>.pngfiles plus a manifest JSON, in a ZIP. - Do all palette math in OKLCH rather than HSL, so hue rotation holds perceived brightness instead of darkening the cool half of a palette. The existing hue-shift buttons stop muddying colors, and the web app, CLI, and MCP server now produce identical pixels from the same spec.
- Extract an exact palette when a sprite has no more distinct colors than were asked for, and never return a duplicate entry. Median-cut splits boxes by pixel count, so on flat pixel art a large region could claim several boxes that averaged to the same color while a small distinct one (a face, a trim) shared a bucket with its neighbour — which made re-tinting a shirt also re-tint the skin.
- Extend the
paletteCLI command with--ramps,--ramp-tolerance,--ramp,--variants,--hue-variants,--hue-step,--out-dir,--name, and--manifest. Existing flags and output keys are unchanged. - Add the
sprite_detect_rampsandsprite_palette_variantsMCP tools, so an agent can inspect a sprite's ramps and write a whole variant set with one call. - Add margin and spacing support for padded sprite sheets —
--margin,--margin-x,--margin-y,--spacing,--spacing-x,--spacing-yon every CLI command that takes--cols/--rows, the same optional args on the MCP sheet tools, and a Margin & spacing control in the Sheet Builder, so sheets with a border and gutters stop slicing a strip of the neighbouring sprite into every frame. - Report the inferred
marginandspacingnext tocols/rowsfromdetectandinfoon all three surfaces, so a padded sheet can be measured once and the numbers fed straight back in. - Add optional per-frame animation durations: a
frameDurationsarray ontagsandmetaJSON (milliseconds,null= fall back to the tag's fps) so key poses can be held longer than in-betweens. The field is only written when a frame has an explicit hold, so existing documents and outputs are unchanged. - Add
--durationto thetags,meta, andgifCLI commands,--tags-jsontogif, aframe_durationsinput on thesprite_generate_tagsandsprite_generate_metaMCP tools, per-frame hold editing in the Tags tool, and duration-aware GIF export. - Add duplicate frame detection and removal — the
dedupeCLI command, thesprite_find_duplicatesMCP tool, a Select unique button in the Sheet Builder, and a Duplicate Frames step in Background Removal. Byte-identical frames always merge. A threshold above 0 also merges frames whose mean absolute RGBA difference, on a 0-255 scale, is at or below it. Alpha counts. - Add tag rewriting to
dedupe(--tags,--tags-out,--respect-tags) andsprite_find_duplicates(tags_path,tags_output_path,respect_tags). Removing frames renumbers later frames, sodeduperewrites each tag range through the renumbering. A range with gaps gets an orderedframeslist,contiguous: false, and a warning.--respect-tagsandrespect_tagsstop a tag losing frames to another tag. - Add engine export: metadata JSON in, an engine-native file out — a Godot 4
SpriteFrames(or per-frameAtlasTexture).tres, a UnityTextureImporter.metasidecar with sliced sprite rects, pivots and physics shapes, an Aseprite-shaped sheet JSON, or a Phaser 3 / PixiJS texture atlas. - Add the
exportCLI command and thesprite_export_engineMCP tool, plus an/exportpage in the web app. All three accept the same input: ametaoutput, ajq -s addmerge ofcollision/pivot/tags, anatlasmanifest, or a merge of those. - Record
grid.margin,grid.spacing,sourceWidthandsourceHeightin thecollision,pivot,tags,metaandpaletteCLI output and the matching MCP tools, so an export of a padded sheet, or one whose size is not a multiple of the cell size, places every region correctly. - Document the export formats at
/docs/reference/engine-export, including the Unity Y-flip and normalized-pivot conventions and each format's limitations — Godot has no slot for pivots or collision, Aseprite drops polygons, and overwriting a Unity.metawithout reusing its guid detaches references. - Stop describing
sprite_generate_tagsoutput as Aseprite tag metadata in the MCP tool description. It is sprite-tools' own JSON shape;export --format asepritewrites the Aseprite file. - Add a Sheet Lint tool at
/lint— nine checks (alpha fringe, frame bleed, pivot drift, duplicate and empty frames, fully opaque frames, non-power-of-two sizes, palette bloat, near-duplicate colours) run over a sheet and drawn onto it, because a report that says "frame 7 bleeds" is far less useful than one that points at the pixels. - Add the
lintCLI command and thesprite_lint_sheetMCP tool — the thing to run first on an unfamiliar sheet, since it reports the detected grid and frame count alongside its findings, and states which rules it skipped and why instead of staying silent. JSON by default,--format textfor humans,--severityto filter,--disable/--only/--setto tune every rule and threshold, and exit code 1 on error-severity findings so it can gate a build. - Add a standalone Background Removal tool at
/background-removal— chroma-key a video, a sprite sheet, or loose images to transparency or a solid fill, auto-crop, and export a ZIP, a stitched sheet, or a single PNG. - Add the
chromaCLI command (aliasremove-bg) and thesprite_remove_backgroundMCP tool, sharing the web app's chroma-key math and defaults. - Add edge extrusion to atlas packing — the
--extrude NCLI flag, theextrudeinput on thesprite_pack_atlasMCP tool, and an Extrude control in the web atlas packer. Each sprite's edge pixels are repeated into the surrounding gutter, and the amount is clamped to--padding, so at padding 0 extrusion is a no-op. - Change atlas packing to extrude 1px by default, so atlas PNGs differ from previous output in the gutter pixels around each sprite. Frame rects in the manifest are unchanged; pass
--extrude 0to restore the old transparent gutter. - Fix the web atlas packer exporting the green frame guides into the PNG — every sprite's outermost pixel row shipped tinted. The guides are now preview-only, so the downloaded atlas is pixel-identical to the CLI's.
- Add pixel-art upscaling to the Pixelate tool, the
pixelateCLI command, and thesprite_pixelateMCP tool — nearest-neighbour plus Scale2x, Scale3x, Eagle, and xBR level 1, so an already-pixelated sprite can be magnified for display without the blur a bilinear resize leaves behind. Every filter only copies existing source pixels, so palettes and transparency come through unchanged. - Add
--upscale-algo/--upscale-factortopixelateandupscale_algo/upscale_factortosprite_pixelate. A factor above 1 is an explicit magnification and replaces the existing--upscale/upscalerestore-to-source-size step, which is unchanged at the default factor of 1. - Read Aseprite working files (
.ase/.aseprite) directly, with no export step. RGBA, grayscale, and indexed files composite with all 19 Aseprite blend modes, layer and cel opacity, and linked cels. - Add the
asepriteCLI command (aliasase) and thesprite_read_asepriteMCP tool. Both report tags, per-frame durations, the layer tree, and the palette as JSON. The CLI writes a sheet PNG by default; the MCP tool writes a sheet or per-frame PNGs on request. - Add an Aseprite source tab to the Sheet Builder and Background Removal pages, with layer, hidden-layer, and animation-tag selection before import.
- Report unsupported or damaged Aseprite content as warnings. The CLI prints them to stderr and the JSON, the MCP tool returns them, and the web app lists them under Decode notes. Tilemap layers, slices, and a group's own blend mode or opacity are not applied, and each one produces a warning.
- Make
sprite-tools asepriteJSON and thesprite_read_asepriteresult one shared shape.sourcenow names the written sheet PNG, and the newasepriteFilekey names the file that was read. - Add
sourceWidth,sourceHeight, and a top-levelframeDurationsarray to Aseprite output, sosprite-tools exportandsprite_export_engineread it directly and keep Aseprite's frame durations. - Add
documentFrameCount,pixelRatio, andlayers[].effectivelyVisibleto the CLI output, andlayers[].referenceto both surfaces. - Stop with an error when a
--layer/layersselection renders no pixels, instead of writing an empty sheet. Naming a reference or hidden layer next to a layer that renders adds a warning. - Keep
pingpong-reversetags in engine export. Aseprite and Phaser JSON writepingpong_reverse, and Godot and Pixi animations bake the frame order starting fromto. - Write a tag's repeat count to Aseprite JSON
frameTagsas"repeat": "N". - Fail engine export on a grid document with
source: nullunless a texture name is given. - Accept a
sprite_read_asepriteresult in engine export. Itsoutput_pathequals itssource, so it no longer counts as image-writing tool output. - Show reference layers, tilemap layers, and hidden layers as dashed, disabled chips in the web Aseprite tab. Hidden layers stay enabled while Include hidden layers is on. A layer, tag, or hidden-layer change after an import re-imports right away.
- Add the dedupe step to Aseprite runs in Background Removal, and warn when a multi-file drop skips
.asefiles. - Add GitHub community health files, issue templates, pull request guidance, and dependency update configuration.
[0.1.0] - Initial public release
- Ship the shared sprite pipeline as a web app, CLI, and MCP server.
- Add collision polygon tracing, pivot detection, animation tags, palette extraction, pixel-art conversion, normal map generation, atlas packing, GIF export, trimming, slicing, and metadata export.