Start here
Declare the cell size, all four outer margins and both internal gaps. Check complete coverage, then compare the first and last crop with known artwork. A grid can fit the image exactly while its origin is wrong.
The original 79×42 sheet split into eight correct 16×16 frames at margins left 2/top 3/right 4/bottom 5 and gaps 3/2. A shifted origin also passed geometry but changed every intended crop. A separate 65×32 control rejected an incomplete column until an explicit right margin of 1 was declared.
What you need
Extract grid-diagnosis.zip. Use assets/asymmetric-sheet.png and compare its crops with the eight numbered PNGs in assets/frames/. The 64×32 plain sheet and 65×32 partial sheet are separate controls.
Tested with: Chrome 154.0.8037.44/macOS: correct, shifted-origin and partial-grid jobs in Cloudflare preview. Inclusive range 2–5 reuses an earlier actual optimized Next.js production run with byte-identical input. Pillow 12.3.0 compared every exported crop; Node 24.22.0 pure geometry is separate.
1. Separate outer margins from gaps between cells

A margin lies outside the first or last cell. A gap lies between cells. Require leading + count × cell + (count − 1) × gap + trailing = length on each axis.
width: 2 + 4×16 + 3×3 + 4 = 79
height: 3 + 2×16 + 1×2 + 5 = 42Coordinates begin at the top left. A crop includes its top/left samples and excludes its bottom/right endpoint. The right margin is not another internal gap.
2. Enter the declaration and inspect all eight crops
- Open the sprite-sheet splitter and use Choose sprite sheet PNG for
asymmetric-sheet.png. - Set both cell dimensions to 16. Set left/top/right/bottom margins to 2/3/4/5.
- Set Horizontal gap (px) to 3 and Vertical gap (px) to 2.
- Check the first crop (2,3,16,16) and last crop (59,21,16,16), then use Split into PNG frames.
- Download the ZIP and manifest. Check each numbered frame, including the middle cells.
The actual eight PNGs all matched independent crops of a separate browser Canvas readback. Their source-global indices remained 0–7. Correct rectangle count alone would not establish correct artwork.
3. Catch a wrong origin that still fits
Keep cell size and gaps unchanged, but enter margins left 0/top 0/right 6/bottom 8. This also describes four columns and two rows. Its first and last origins are now (0,0) and (57,18).
The actual export followed those declared rectangles exactly, but every crop differed from its intended frame. The first wrong crop differed at 118 pixels; its pixel (1,7) was transparent [0,0,0,0] instead of the correct border [28,32,48,255].


This is the important failure: complete coverage cannot infer which margin follows the artwork. Restore the known declaration and compare visible frame identity before accepting the settings.
4. Reject an incomplete column before exporting
Choose partial-sheet.png, 65×32. With 16×16 cells, zero margins and zero gaps, the tool reported Declared grid must cover complete cells exactly between its margins and disabled the split button.
An explicit right margin of 1 makes a different valid declaration: four complete columns followed by one outside column. With that setting, the actual eight exported crops all matched their 16×16 source rectangles. The tool did not infer or silently discard the extra column.
Wrong cell width 17, gapX 2 or zero margins on the asymmetric sheet also fail complete coverage in the source checks. Negative/fractional values and reversed or out-of-range selections reject.
5. Keep global source IDs when selecting a range
On the correct asymmetric declaration, enable Limit frame range (zero-based, inclusive), set Start frame to 2 and End frame to 5.
sourceFrameIndex: 2 3 4 5
source origin: (40,3) (59,3) (2,21) (21,21)
output frameIndex: 0 1 2 3An earlier actual run of the byte-identical input verified all four crops and these manifest rectangles. It is retained evidence from optimized Next.js production; the current Cloudflare round verified the complete, shifted and partial cases. The first selected source remains frame 2 even though its output index is 0.
At most 32 frames may be selected. A larger grid needs an explicit range; this workflow does not automatically segment irregular sprites.
6. Distinguish a bad cut from browser alpha normalization
Each original includes hidden RGB at alpha 0 and partial-alpha probes. For each full input here, raw PNG-to-Canvas readback changed 32 pixels/72 RGB channel bytes, with no alpha-channel changes. The exported crops matched that Canvas reference exactly.
Pure source cropping preserves all RGBA samples. Browser output does not promise that same raw-byte fidelity. Compare equivalent decoded references before blaming the cut lines for an alpha/color difference.
To reproduce only the fixed original references, use Node 24 in the extracted directory:
node --test fixture.test.mjs
node generate.mjs
node generate.mjs --checkThe source runner and repository geometry tests are separate from the recorded browser exports. A native importer can expose different margin controls; this generic declaration is not proof of its behavior.