QUICKUPSCALE

PRACTICAL GUIDE

Sprite sheet tools and workflows

Keep sprite frame identity across filenames and manual order

Start here

Keep each original frame's selection index, safe filename and desired output position together. Choose the complete order, then check the pixels in that order. Alphabetical filenames or an archive viewer's listing cannot replace this mapping.

Expected result:

The actual eight-frame job used source order 3,0,7,1,6,2,5,4 and produced one 64×32 sheet. All eight cells and 32 marker bits matched the separately captured source Canvas pixels. Its manifest preserved source identity and aliases assigned in selection order.

What you need

Extract frame-order.zip. The eight original 16×16 PNGs have unique physical names source-00.png through source-07.png. assets/declaration.json separately records numeric-looking, Unicode and case-equivalent display names.

Tested with: Chrome 154.0.8037.44/macOS, actual Cloudflare preview; controlled browser File/DataTransfer selection from unchanged original PNG bytes. Pillow 12.3.0 verified all cells/markers/ZIP payloads. This is not an OS chooser or filesystem Unicode/case test. Node 24.22.0 references are separate.

1. Record identity before changing names or positions

The recorded selection indices 0–7 had display names frame1.png, frame10.png, frame2.png, 雪 walk.png, Idle.PNG, idle.png, e\u0301.png, é.png. The last two spellings are canonically equivalent, yet refer to different original PNGs.

The exact name case used browser File objects supplied through DataTransfer with unchanged original bytes. That exercises the web File/name path; it does not prove that an OS chooser preserves those spellings as separate physical files. Use the unique ASCII paths for ordinary filesystem extraction.

If you start from a sheet, split a known grid and retain its source-frame mapping first. The recorded name case here selected the supplied original frames directly; it was not a fresh split-to-maker lineage run.

2. Set the complete manual sequence

Open the sprite-sheet maker, choose all eight frames, and record their actual selection identities. Select Manual order. Use Move up and Move down until the numbered artwork follows:

source indices: 0,1,2,3,4,5,6,7
manual order:   3,0,7,1,6,2,5,4
output index:   0,1,2,3,4,5,6,7

The recorded round used 17 real move-up clicks. Choose Grid, set Columns to 4, keep Require equal frame dimensions, then use Build sprite sheet. Download its ZIP and manifest.

For your own chooser selection, map the numbered originals to the actual source indices before following this sequence. An empty/missing/duplicate/out-of-range source index is an invalid complete permutation; the standalone source controls check those failures.

3. Read source aliases independently of output positions

The maker assigns safe source aliases in selection order, before manual placement. NFC-equivalent and case-equivalent names receive distinct suffixes. The actual output mapping was:

Output indexSource indexOriginal display nameManifest source aliasCell origin
03雪 walk.png雪 walk.png0,0
10frame1.pngframe1.png16,0
27é.pngé-2.png32,0
31frame10.pngframe10.png48,0
46e + combining acute.pngé.png0,16
52frame2.pngframe2.png16,16
65idle.pngidle-2.png32,16
74Idle.PNGIdle.png48,16

Source 7 kept é-2.png, source 4 Idle.png and source 5 idle-2.png after moving. The alias does not become a new source identity. Check layout.sourceOrder, each frame's sourceIndex, and its contentRect/allocatedRect.

The unchanged standalone reference assigns names after its declared order, so its reference ZIP instead includes é.png for source 7 and Idle-2.png for source 4. That reference declaration is not the actual tool manifest. Its additional source-only controls include CON.png → _CON.png.

4. Verify every cell and its original marker

Original eight-frame source reference arranged in the declared manual order
Original 64×32 source reference. The actual browser sheet used the same positions but normalized some alpha/color samples.

Output cell i starts at ((i % 4) × 16, floor(i / 4) × 16). Inspect every 16×16 cell, including the middle frames. On row 15, pixels at x=2,4,6,8 are gold when bits 0–3 of the original frame index are set, otherwise transparent black.

The actual sheet passed all 32 marker bits and all 8 full-cell comparisons against separate source Canvas readbacks. Its ZIP contained manifest.json and sprite-sheet.png; the separately downloaded manifest and sheet were byte-identical to those payloads. CRC and safe paths passed too.

Actual downloaded 64 by 32 browser sheet in the recorded manual order
Actual downloaded PNG:64×32, copied unchanged from the browser ZIP.

An intact ZIP checksum only establishes payload integrity. It cannot tell you that a valid PNG was assigned to the intended source frame.

5. Separate a wrong sequence from alpha/color changes

A lexical sequence frame1, frame10, frame2 corresponds to sources 0,1,2. If you intended 1,2,10, explicitly choose 0,2,1 instead. This source-reference counterexample is not a claim that the maker's Natural filename order mode sorts lexically.

Names do not supply missing frame delays, tags, pivots or animation metadata. Renaming a PNG without correcting the mapping does not repair a misplaced cell.

Raw PNG-to-Canvas conversion changed 32 pixels/72 RGB channel bytes across the eight originals, with no alpha-channel changes. The actual placed sheet matched those Canvas pixels exactly. Pure source placement preserves hidden RGB; browser decoding/canvas/encoding does not promise the same raw RGBA fidelity.

6. Reproduce the separate reference project

With Node 24 in the extracted frame-order directory, no dependency install is required:

node --test fixture.test.mjs
node generate.mjs
node generate.mjs --check

This reproduces the original frames, after-order reference aliases, reference sheet and reference ZIP. Equal files keep modification times; missing/stale/extra outputs fail the read-only check. It does not replay the browser selection, move controls or worker export.

Sources and next steps